]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
illuminated surfaces are now sorted by texture, giving a good fps
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
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.
8
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.
12
13 See the GNU General Public License for more details.
14
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.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30
31 mempool_t *r_main_mempool;
32 rtexturepool_t *r_main_texturepool;
33
34 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
35
36 static qboolean r_loadnormalmap;
37 static qboolean r_loadgloss;
38 qboolean r_loadfog;
39 static qboolean r_loaddds;
40 static qboolean r_savedds;
41
42 //
43 // screen size info
44 //
45 r_refdef_t r_refdef;
46
47 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
48 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
49 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
50 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
51 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)"};
52 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
53 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
54 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
55
56 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
57 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
58 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
59 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
60 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
61
62 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"};
63 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
64 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
65 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
66 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
67 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
68 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)"};
69 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
70 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
71 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"};
72 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"};
73 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
74 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"};
75 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"};
76 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"};
77 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
78 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
79 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
80 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
81 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
82 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
83 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
84 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
85 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
86 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
87 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
88 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
89 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
90
91 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
92 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
93 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
94
95 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
96 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
97 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
98 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."};
99 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
100 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
101 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
102 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."};
103 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
104 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
105 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
106 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
107 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"};
108 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
109 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
110 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
111 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
112 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
113 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
114
115 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
116 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
117 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
118 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
119 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
120 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
121 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
122 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
123
124 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
125 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
126
127 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
128 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
129 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
130 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
131 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
132
133 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
134 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
135 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
136
137 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)"};
138 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
139 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
140 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
141 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
142 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)"};
143 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)"};
144 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)"};
145 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)"};
146 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
147 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
148 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
149 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
150
151 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)"};
152 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
153 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"};
154 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
155 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
156 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
157
158 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
159 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
160 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
161 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
162
163 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
164 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
165 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
166 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
167 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
168 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
169 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
170
171 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
172 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
173 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
174 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)"};
175
176 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"};
177
178 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"};
179
180 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
181
182 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
183 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
184 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"};
185 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
186 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
187 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
188 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
189 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
190
191 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
192 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
193
194 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
195
196 extern cvar_t v_glslgamma;
197
198 extern qboolean v_flipped_state;
199
200 static struct r_bloomstate_s
201 {
202         qboolean enabled;
203         qboolean hdr;
204
205         int bloomwidth, bloomheight;
206
207         int screentexturewidth, screentextureheight;
208         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
209
210         int bloomtexturewidth, bloomtextureheight;
211         rtexture_t *texture_bloom;
212
213         // arrays for rendering the screen passes
214         float screentexcoord2f[8];
215         float bloomtexcoord2f[8];
216         float offsettexcoord2f[8];
217
218         r_viewport_t viewport;
219 }
220 r_bloomstate;
221
222 r_waterstate_t r_waterstate;
223
224 /// shadow volume bsp struct with automatically growing nodes buffer
225 svbsp_t r_svbsp;
226
227 rtexture_t *r_texture_blanknormalmap;
228 rtexture_t *r_texture_white;
229 rtexture_t *r_texture_grey128;
230 rtexture_t *r_texture_black;
231 rtexture_t *r_texture_notexture;
232 rtexture_t *r_texture_whitecube;
233 rtexture_t *r_texture_normalizationcube;
234 rtexture_t *r_texture_fogattenuation;
235 rtexture_t *r_texture_fogheighttexture;
236 rtexture_t *r_texture_gammaramps;
237 unsigned int r_texture_gammaramps_serial;
238 //rtexture_t *r_texture_fogintensity;
239 rtexture_t *r_texture_reflectcube;
240
241 // TODO: hash lookups?
242 typedef struct cubemapinfo_s
243 {
244         char basename[64];
245         rtexture_t *texture;
246 }
247 cubemapinfo_t;
248
249 int r_texture_numcubemaps;
250 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
251
252 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
253 unsigned int r_numqueries;
254 unsigned int r_maxqueries;
255
256 typedef struct r_qwskincache_s
257 {
258         char name[MAX_QPATH];
259         skinframe_t *skinframe;
260 }
261 r_qwskincache_t;
262
263 static r_qwskincache_t *r_qwskincache;
264 static int r_qwskincache_size;
265
266 /// vertex coordinates for a quad that covers the screen exactly
267 const float r_screenvertex3f[12] =
268 {
269         0, 0, 0,
270         1, 0, 0,
271         1, 1, 0,
272         0, 1, 0
273 };
274
275 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
276 {
277         int i;
278         for (i = 0;i < verts;i++)
279         {
280                 out[0] = in[0] * r;
281                 out[1] = in[1] * g;
282                 out[2] = in[2] * b;
283                 out[3] = in[3];
284                 in += 4;
285                 out += 4;
286         }
287 }
288
289 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
290 {
291         int i;
292         for (i = 0;i < verts;i++)
293         {
294                 out[0] = r;
295                 out[1] = g;
296                 out[2] = b;
297                 out[3] = a;
298                 out += 4;
299         }
300 }
301
302 // FIXME: move this to client?
303 void FOG_clear(void)
304 {
305         if (gamemode == GAME_NEHAHRA)
306         {
307                 Cvar_Set("gl_fogenable", "0");
308                 Cvar_Set("gl_fogdensity", "0.2");
309                 Cvar_Set("gl_fogred", "0.3");
310                 Cvar_Set("gl_foggreen", "0.3");
311                 Cvar_Set("gl_fogblue", "0.3");
312         }
313         r_refdef.fog_density = 0;
314         r_refdef.fog_red = 0;
315         r_refdef.fog_green = 0;
316         r_refdef.fog_blue = 0;
317         r_refdef.fog_alpha = 1;
318         r_refdef.fog_start = 0;
319         r_refdef.fog_end = 16384;
320         r_refdef.fog_height = 1<<30;
321         r_refdef.fog_fadedepth = 128;
322         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
323 }
324
325 static void R_BuildBlankTextures(void)
326 {
327         unsigned char data[4];
328         data[2] = 128; // normal X
329         data[1] = 128; // normal Y
330         data[0] = 255; // normal Z
331         data[3] = 128; // height
332         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
333         data[0] = 255;
334         data[1] = 255;
335         data[2] = 255;
336         data[3] = 255;
337         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
338         data[0] = 128;
339         data[1] = 128;
340         data[2] = 128;
341         data[3] = 255;
342         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
343         data[0] = 0;
344         data[1] = 0;
345         data[2] = 0;
346         data[3] = 255;
347         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
348 }
349
350 static void R_BuildNoTexture(void)
351 {
352         int x, y;
353         unsigned char pix[16][16][4];
354         // this makes a light grey/dark grey checkerboard texture
355         for (y = 0;y < 16;y++)
356         {
357                 for (x = 0;x < 16;x++)
358                 {
359                         if ((y < 8) ^ (x < 8))
360                         {
361                                 pix[y][x][0] = 128;
362                                 pix[y][x][1] = 128;
363                                 pix[y][x][2] = 128;
364                                 pix[y][x][3] = 255;
365                         }
366                         else
367                         {
368                                 pix[y][x][0] = 64;
369                                 pix[y][x][1] = 64;
370                                 pix[y][x][2] = 64;
371                                 pix[y][x][3] = 255;
372                         }
373                 }
374         }
375         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
376 }
377
378 static void R_BuildWhiteCube(void)
379 {
380         unsigned char data[6*1*1*4];
381         memset(data, 255, sizeof(data));
382         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
383 }
384
385 static void R_BuildNormalizationCube(void)
386 {
387         int x, y, side;
388         vec3_t v;
389         vec_t s, t, intensity;
390 #define NORMSIZE 64
391         unsigned char *data;
392         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
393         for (side = 0;side < 6;side++)
394         {
395                 for (y = 0;y < NORMSIZE;y++)
396                 {
397                         for (x = 0;x < NORMSIZE;x++)
398                         {
399                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
400                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
401                                 switch(side)
402                                 {
403                                 default:
404                                 case 0:
405                                         v[0] = 1;
406                                         v[1] = -t;
407                                         v[2] = -s;
408                                         break;
409                                 case 1:
410                                         v[0] = -1;
411                                         v[1] = -t;
412                                         v[2] = s;
413                                         break;
414                                 case 2:
415                                         v[0] = s;
416                                         v[1] = 1;
417                                         v[2] = t;
418                                         break;
419                                 case 3:
420                                         v[0] = s;
421                                         v[1] = -1;
422                                         v[2] = -t;
423                                         break;
424                                 case 4:
425                                         v[0] = s;
426                                         v[1] = -t;
427                                         v[2] = 1;
428                                         break;
429                                 case 5:
430                                         v[0] = -s;
431                                         v[1] = -t;
432                                         v[2] = -1;
433                                         break;
434                                 }
435                                 intensity = 127.0f / sqrt(DotProduct(v, v));
436                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
437                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
438                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
439                                 data[((side*64+y)*64+x)*4+3] = 255;
440                         }
441                 }
442         }
443         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
444         Mem_Free(data);
445 }
446
447 static void R_BuildFogTexture(void)
448 {
449         int x, b;
450 #define FOGWIDTH 256
451         unsigned char data1[FOGWIDTH][4];
452         //unsigned char data2[FOGWIDTH][4];
453         double d, r, alpha;
454
455         r_refdef.fogmasktable_start = r_refdef.fog_start;
456         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
457         r_refdef.fogmasktable_range = r_refdef.fogrange;
458         r_refdef.fogmasktable_density = r_refdef.fog_density;
459
460         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
461         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
462         {
463                 d = (x * r - r_refdef.fogmasktable_start);
464                 if(developer_extra.integer)
465                         Con_DPrintf("%f ", d);
466                 d = max(0, d);
467                 if (r_fog_exp2.integer)
468                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
469                 else
470                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
471                 if(developer_extra.integer)
472                         Con_DPrintf(" : %f ", alpha);
473                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
474                 if(developer_extra.integer)
475                         Con_DPrintf(" = %f\n", alpha);
476                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
477         }
478
479         for (x = 0;x < FOGWIDTH;x++)
480         {
481                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
482                 data1[x][0] = b;
483                 data1[x][1] = b;
484                 data1[x][2] = b;
485                 data1[x][3] = 255;
486                 //data2[x][0] = 255 - b;
487                 //data2[x][1] = 255 - b;
488                 //data2[x][2] = 255 - b;
489                 //data2[x][3] = 255;
490         }
491         if (r_texture_fogattenuation)
492         {
493                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
494                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
495         }
496         else
497         {
498                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
499                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
500         }
501 }
502
503 static void R_BuildFogHeightTexture(void)
504 {
505         unsigned char *inpixels;
506         int size;
507         int x;
508         int y;
509         int j;
510         float c[4];
511         float f;
512         inpixels = NULL;
513         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
514         if (r_refdef.fogheighttexturename[0])
515                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
516         if (!inpixels)
517         {
518                 r_refdef.fog_height_tablesize = 0;
519                 if (r_texture_fogheighttexture)
520                         R_FreeTexture(r_texture_fogheighttexture);
521                 r_texture_fogheighttexture = NULL;
522                 if (r_refdef.fog_height_table2d)
523                         Mem_Free(r_refdef.fog_height_table2d);
524                 r_refdef.fog_height_table2d = NULL;
525                 if (r_refdef.fog_height_table1d)
526                         Mem_Free(r_refdef.fog_height_table1d);
527                 r_refdef.fog_height_table1d = NULL;
528                 return;
529         }
530         size = image_width;
531         r_refdef.fog_height_tablesize = size;
532         r_refdef.fog_height_table1d = Mem_Alloc(r_main_mempool, size * 4);
533         r_refdef.fog_height_table2d = Mem_Alloc(r_main_mempool, size * size * 4);
534         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
535         Mem_Free(inpixels);
536         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
537         // average fog color table accounting for every fog layer between a point
538         // and the camera.  (Note: attenuation is handled separately!)
539         for (y = 0;y < size;y++)
540         {
541                 for (x = 0;x < size;x++)
542                 {
543                         Vector4Clear(c);
544                         f = 0;
545                         if (x < y)
546                         {
547                                 for (j = x;j <= y;j++)
548                                 {
549                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
550                                         f++;
551                                 }
552                         }
553                         else
554                         {
555                                 for (j = x;j >= y;j--)
556                                 {
557                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
558                                         f++;
559                                 }
560                         }
561                         f = 1.0f / f;
562                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
563                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
564                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
565                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
566                 }
567         }
568         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
569 }
570
571 //=======================================================================================================================================================
572
573 static const char *builtinshaderstring =
574 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
575 "// written by Forest 'LordHavoc' Hale\n"
576 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
577 "\n"
578 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
579 "# define USEFOG\n"
580 "#endif\n"
581 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
582 "#define USELIGHTMAP\n"
583 "#endif\n"
584 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
585 "#define USEEYEVECTOR\n"
586 "#endif\n"
587 "\n"
588 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
589 "# extension GL_ARB_texture_rectangle : enable\n"
590 "#endif\n"
591 "\n"
592 "#ifdef USESHADOWMAP2D\n"
593 "# ifdef GL_EXT_gpu_shader4\n"
594 "#   extension GL_EXT_gpu_shader4 : enable\n"
595 "# endif\n"
596 "# ifdef GL_ARB_texture_gather\n"
597 "#   extension GL_ARB_texture_gather : enable\n"
598 "# else\n"
599 "#   ifdef GL_AMD_texture_texture4\n"
600 "#     extension GL_AMD_texture_texture4 : enable\n"
601 "#   endif\n"
602 "# endif\n"
603 "#endif\n"
604 "\n"
605 "#ifdef USESHADOWMAPCUBE\n"
606 "# extension GL_EXT_gpu_shader4 : enable\n"
607 "#endif\n"
608 "\n"
609 "//#ifdef USESHADOWSAMPLER\n"
610 "//# extension GL_ARB_shadow : enable\n"
611 "//#endif\n"
612 "\n"
613 "//#ifdef __GLSL_CG_DATA_TYPES\n"
614 "//# define myhalf half\n"
615 "//# define myhalf2 half2\n"
616 "//# define myhalf3 half3\n"
617 "//# define myhalf4 half4\n"
618 "//#else\n"
619 "# define myhalf float\n"
620 "# define myhalf2 vec2\n"
621 "# define myhalf3 vec3\n"
622 "# define myhalf4 vec4\n"
623 "//#endif\n"
624 "\n"
625 "#ifdef VERTEX_SHADER\n"
626 "uniform mat4 ModelViewProjectionMatrix;\n"
627 "#endif\n"
628 "\n"
629 "#ifdef MODE_DEPTH_OR_SHADOW\n"
630 "#ifdef VERTEX_SHADER\n"
631 "void main(void)\n"
632 "{\n"
633 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
634 "}\n"
635 "#endif\n"
636 "#else // !MODE_DEPTH_ORSHADOW\n"
637 "\n"
638 "\n"
639 "\n"
640 "\n"
641 "#ifdef MODE_SHOWDEPTH\n"
642 "#ifdef VERTEX_SHADER\n"
643 "void main(void)\n"
644 "{\n"
645 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
646 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
647 "}\n"
648 "#endif\n"
649 "\n"
650 "#ifdef FRAGMENT_SHADER\n"
651 "void main(void)\n"
652 "{\n"
653 "       gl_FragColor = gl_Color;\n"
654 "}\n"
655 "#endif\n"
656 "#else // !MODE_SHOWDEPTH\n"
657 "\n"
658 "\n"
659 "\n"
660 "\n"
661 "#ifdef MODE_POSTPROCESS\n"
662 "varying vec2 TexCoord1;\n"
663 "varying vec2 TexCoord2;\n"
664 "\n"
665 "#ifdef VERTEX_SHADER\n"
666 "void main(void)\n"
667 "{\n"
668 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
669 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
670 "#ifdef USEBLOOM\n"
671 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
672 "#endif\n"
673 "}\n"
674 "#endif\n"
675 "\n"
676 "#ifdef FRAGMENT_SHADER\n"
677 "uniform sampler2D Texture_First;\n"
678 "#ifdef USEBLOOM\n"
679 "uniform sampler2D Texture_Second;\n"
680 "#endif\n"
681 "#ifdef USEGAMMARAMPS\n"
682 "uniform sampler2D Texture_GammaRamps;\n"
683 "#endif\n"
684 "#ifdef USESATURATION\n"
685 "uniform float Saturation;\n"
686 "#endif\n"
687 "#ifdef USEVIEWTINT\n"
688 "uniform vec4 ViewTintColor;\n"
689 "#endif\n"
690 "//uncomment these if you want to use them:\n"
691 "uniform vec4 UserVec1;\n"
692 "uniform vec4 UserVec2;\n"
693 "// uniform vec4 UserVec3;\n"
694 "// uniform vec4 UserVec4;\n"
695 "// uniform float ClientTime;\n"
696 "uniform vec2 PixelSize;\n"
697 "void main(void)\n"
698 "{\n"
699 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
700 "#ifdef USEBLOOM\n"
701 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
702 "#endif\n"
703 "#ifdef USEVIEWTINT\n"
704 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
705 "#endif\n"
706 "\n"
707 "#ifdef USEPOSTPROCESSING\n"
708 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
709 "// 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"
710 "       float sobel = 1.0;\n"
711 "       // vec2 ts = textureSize(Texture_First, 0);\n"
712 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
713 "       vec2 px = PixelSize;\n"
714 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
715 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
716 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
717 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
718 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
719 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
720 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
721 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
722 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
723 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
724 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
725 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
726 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
727 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
728 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
729 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
730 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
731 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
732 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
733 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
734 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
735 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
736 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
737 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
738 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
739 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
740 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
741 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
742 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
743 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
744 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
745 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
746 "#endif\n"
747 "\n"
748 "#ifdef USESATURATION\n"
749 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
750 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
751 "       // 'vampire sight' effect, wheres red is compensated\n"
752 "       #ifdef SATURATION_REDCOMPENSATE\n"
753 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
754 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
755 "               gl_FragColor.r += rboost;\n"
756 "       #else\n"
757 "               // normal desaturation\n"
758 "               //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
759 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
760 "       #endif\n"
761 "#endif\n"
762 "\n"
763 "#ifdef USEGAMMARAMPS\n"
764 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
765 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
766 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
767 "#endif\n"
768 "}\n"
769 "#endif\n"
770 "#else // !MODE_POSTPROCESS\n"
771 "\n"
772 "\n"
773 "\n"
774 "\n"
775 "#ifdef MODE_GENERIC\n"
776 "#ifdef USEDIFFUSE\n"
777 "varying vec2 TexCoord1;\n"
778 "#endif\n"
779 "#ifdef USESPECULAR\n"
780 "varying vec2 TexCoord2;\n"
781 "#endif\n"
782 "#ifdef VERTEX_SHADER\n"
783 "void main(void)\n"
784 "{\n"
785 "       gl_FrontColor = gl_Color;\n"
786 "#ifdef USEDIFFUSE\n"
787 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
788 "#endif\n"
789 "#ifdef USESPECULAR\n"
790 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
791 "#endif\n"
792 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
793 "}\n"
794 "#endif\n"
795 "\n"
796 "#ifdef FRAGMENT_SHADER\n"
797 "#ifdef USEDIFFUSE\n"
798 "uniform sampler2D Texture_First;\n"
799 "#endif\n"
800 "#ifdef USESPECULAR\n"
801 "uniform sampler2D Texture_Second;\n"
802 "#endif\n"
803 "\n"
804 "void main(void)\n"
805 "{\n"
806 "       gl_FragColor = gl_Color;\n"
807 "#ifdef USEDIFFUSE\n"
808 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
809 "#endif\n"
810 "\n"
811 "#ifdef USESPECULAR\n"
812 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
813 "# ifdef USECOLORMAPPING\n"
814 "       gl_FragColor *= tex2;\n"
815 "# endif\n"
816 "# ifdef USEGLOW\n"
817 "       gl_FragColor += tex2;\n"
818 "# endif\n"
819 "# ifdef USEVERTEXTEXTUREBLEND\n"
820 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
821 "# endif\n"
822 "#endif\n"
823 "}\n"
824 "#endif\n"
825 "#else // !MODE_GENERIC\n"
826 "\n"
827 "\n"
828 "\n"
829 "\n"
830 "#ifdef MODE_BLOOMBLUR\n"
831 "varying TexCoord;\n"
832 "#ifdef VERTEX_SHADER\n"
833 "void main(void)\n"
834 "{\n"
835 "       gl_FrontColor = gl_Color;\n"
836 "       TexCoord = gl_MultiTexCoord0.xy;\n"
837 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
838 "}\n"
839 "#endif\n"
840 "\n"
841 "#ifdef FRAGMENT_SHADER\n"
842 "uniform sampler2D Texture_First;\n"
843 "uniform vec4 BloomBlur_Parameters;\n"
844 "\n"
845 "void main(void)\n"
846 "{\n"
847 "       int i;\n"
848 "       vec2 tc = TexCoord;\n"
849 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
850 "       tc += BloomBlur_Parameters.xy;\n"
851 "       for (i = 1;i < SAMPLES;i++)\n"
852 "       {\n"
853 "               color += texture2D(Texture_First, tc).rgb;\n"
854 "               tc += BloomBlur_Parameters.xy;\n"
855 "       }\n"
856 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
857 "}\n"
858 "#endif\n"
859 "#else // !MODE_BLOOMBLUR\n"
860 "#ifdef MODE_REFRACTION\n"
861 "varying vec2 TexCoord;\n"
862 "varying vec4 ModelViewProjectionPosition;\n"
863 "uniform mat4 TexMatrix;\n"
864 "#ifdef VERTEX_SHADER\n"
865 "\n"
866 "void main(void)\n"
867 "{\n"
868 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
869 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
870 "       ModelViewProjectionPosition = gl_Position;\n"
871 "}\n"
872 "#endif\n"
873 "\n"
874 "#ifdef FRAGMENT_SHADER\n"
875 "uniform sampler2D Texture_Normal;\n"
876 "uniform sampler2D Texture_Refraction;\n"
877 "uniform sampler2D Texture_Reflection;\n"
878 "\n"
879 "uniform vec4 DistortScaleRefractReflect;\n"
880 "uniform vec4 ScreenScaleRefractReflect;\n"
881 "uniform vec4 ScreenCenterRefractReflect;\n"
882 "uniform vec4 RefractColor;\n"
883 "uniform vec4 ReflectColor;\n"
884 "uniform float ReflectFactor;\n"
885 "uniform float ReflectOffset;\n"
886 "\n"
887 "void main(void)\n"
888 "{\n"
889 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
890 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
891 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
892 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
893 "       // FIXME temporary hack to detect the case that the reflection\n"
894 "       // gets blackened at edges due to leaving the area that contains actual\n"
895 "       // content.\n"
896 "       // Remove this 'ack once we have a better way to stop this thing from\n"
897 "       // 'appening.\n"
898 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
899 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
900 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
901 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
902 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
903 "       gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
904 "}\n"
905 "#endif\n"
906 "#else // !MODE_REFRACTION\n"
907 "\n"
908 "\n"
909 "\n"
910 "\n"
911 "#ifdef MODE_WATER\n"
912 "varying vec2 TexCoord;\n"
913 "varying vec3 EyeVector;\n"
914 "varying vec4 ModelViewProjectionPosition;\n"
915 "#ifdef VERTEX_SHADER\n"
916 "uniform vec3 EyePosition;\n"
917 "uniform mat4 TexMatrix;\n"
918 "\n"
919 "void main(void)\n"
920 "{\n"
921 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
922 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
923 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
924 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
925 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
926 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
927 "       ModelViewProjectionPosition = gl_Position;\n"
928 "}\n"
929 "#endif\n"
930 "\n"
931 "#ifdef FRAGMENT_SHADER\n"
932 "uniform sampler2D Texture_Normal;\n"
933 "uniform sampler2D Texture_Refraction;\n"
934 "uniform sampler2D Texture_Reflection;\n"
935 "\n"
936 "uniform vec4 DistortScaleRefractReflect;\n"
937 "uniform vec4 ScreenScaleRefractReflect;\n"
938 "uniform vec4 ScreenCenterRefractReflect;\n"
939 "uniform vec4 RefractColor;\n"
940 "uniform vec4 ReflectColor;\n"
941 "uniform float ReflectFactor;\n"
942 "uniform float ReflectOffset;\n"
943 "uniform float ClientTime;\n"
944 "#ifdef USENORMALMAPSCROLLBLEND\n"
945 "uniform vec2 NormalmapScrollBlend;\n"
946 "#endif\n"
947 "\n"
948 "void main(void)\n"
949 "{\n"
950 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
951 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
952 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
953 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
954 "       // slight water animation via 2 layer scrolling (todo: tweak)\n"
955 "       #ifdef USENORMALMAPSCROLLBLEND\n"
956 "               vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
957 "               normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
958 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
959 "       #else\n"
960 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
961 "       #endif\n"
962 "       // FIXME temporary hack to detect the case that the reflection\n"
963 "       // gets blackened at edges due to leaving the area that contains actual\n"
964 "       // content.\n"
965 "       // Remove this 'ack once we have a better way to stop this thing from\n"
966 "       // 'appening.\n"
967 "       float f1 = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
968 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
969 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
970 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
971 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f1);\n"
972 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
973 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
974 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
975 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
976 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
977 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
978 "       gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
979 "       gl_FragColor.a = f1 + 0.5;\n"
980 "}\n"
981 "#endif\n"
982 "#else // !MODE_WATER\n"
983 "\n"
984 "\n"
985 "\n"
986 "\n"
987 "// common definitions between vertex shader and fragment shader:\n"
988 "\n"
989 "varying vec2 TexCoord;\n"
990 "#ifdef USEVERTEXTEXTUREBLEND\n"
991 "varying vec2 TexCoord2;\n"
992 "#endif\n"
993 "#ifdef USELIGHTMAP\n"
994 "varying vec2 TexCoordLightmap;\n"
995 "#endif\n"
996 "\n"
997 "#ifdef MODE_LIGHTSOURCE\n"
998 "varying vec3 CubeVector;\n"
999 "#endif\n"
1000 "\n"
1001 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1002 "varying vec3 LightVector;\n"
1003 "#endif\n"
1004 "\n"
1005 "#ifdef USEEYEVECTOR\n"
1006 "varying vec3 EyeVector;\n"
1007 "#endif\n"
1008 "#ifdef USEFOG\n"
1009 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1010 "#endif\n"
1011 "\n"
1012 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1013 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1014 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1015 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1016 "#endif\n"
1017 "\n"
1018 "#ifdef USEREFLECTION\n"
1019 "varying vec4 ModelViewProjectionPosition;\n"
1020 "#endif\n"
1021 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1022 "uniform vec3 LightPosition;\n"
1023 "varying vec4 ModelViewPosition;\n"
1024 "#endif\n"
1025 "\n"
1026 "#ifdef MODE_LIGHTSOURCE\n"
1027 "uniform vec3 LightPosition;\n"
1028 "#endif\n"
1029 "uniform vec3 EyePosition;\n"
1030 "#ifdef MODE_LIGHTDIRECTION\n"
1031 "uniform vec3 LightDir;\n"
1032 "#endif\n"
1033 "uniform vec4 FogPlane;\n"
1034 "\n"
1035 "#ifdef USESHADOWMAPORTHO\n"
1036 "varying vec3 ShadowMapTC;\n"
1037 "#endif\n"
1038 "\n"
1039 "\n"
1040 "\n"
1041 "\n"
1042 "\n"
1043 "// 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"
1044 "\n"
1045 "// fragment shader specific:\n"
1046 "#ifdef FRAGMENT_SHADER\n"
1047 "\n"
1048 "uniform sampler2D Texture_Normal;\n"
1049 "uniform sampler2D Texture_Color;\n"
1050 "uniform sampler2D Texture_Gloss;\n"
1051 "#ifdef USEGLOW\n"
1052 "uniform sampler2D Texture_Glow;\n"
1053 "#endif\n"
1054 "#ifdef USEVERTEXTEXTUREBLEND\n"
1055 "uniform sampler2D Texture_SecondaryNormal;\n"
1056 "uniform sampler2D Texture_SecondaryColor;\n"
1057 "uniform sampler2D Texture_SecondaryGloss;\n"
1058 "#ifdef USEGLOW\n"
1059 "uniform sampler2D Texture_SecondaryGlow;\n"
1060 "#endif\n"
1061 "#endif\n"
1062 "#ifdef USECOLORMAPPING\n"
1063 "uniform sampler2D Texture_Pants;\n"
1064 "uniform sampler2D Texture_Shirt;\n"
1065 "#endif\n"
1066 "#ifdef USEFOG\n"
1067 "#ifdef USEFOGHEIGHTTEXTURE\n"
1068 "uniform sampler2D Texture_FogHeightTexture;\n"
1069 "#endif\n"
1070 "uniform sampler2D Texture_FogMask;\n"
1071 "#endif\n"
1072 "#ifdef USELIGHTMAP\n"
1073 "uniform sampler2D Texture_Lightmap;\n"
1074 "#endif\n"
1075 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1076 "uniform sampler2D Texture_Deluxemap;\n"
1077 "#endif\n"
1078 "#ifdef USEREFLECTION\n"
1079 "uniform sampler2D Texture_Reflection;\n"
1080 "#endif\n"
1081 "\n"
1082 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1083 "uniform sampler2D Texture_ScreenDepth;\n"
1084 "uniform sampler2D Texture_ScreenNormalMap;\n"
1085 "#endif\n"
1086 "#ifdef USEDEFERREDLIGHTMAP\n"
1087 "uniform sampler2D Texture_ScreenDiffuse;\n"
1088 "uniform sampler2D Texture_ScreenSpecular;\n"
1089 "#endif\n"
1090 "\n"
1091 "uniform myhalf3 Color_Pants;\n"
1092 "uniform myhalf3 Color_Shirt;\n"
1093 "uniform myhalf3 FogColor;\n"
1094 "\n"
1095 "#ifdef USEFOG\n"
1096 "uniform float FogRangeRecip;\n"
1097 "uniform float FogPlaneViewDist;\n"
1098 "uniform float FogHeightFade;\n"
1099 "vec3 FogVertex(vec3 surfacecolor)\n"
1100 "{\n"
1101 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1102 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1103 "       float fogfrac;\n"
1104 "#ifdef USEFOGHEIGHTTEXTURE\n"
1105 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1106 "       fogfrac = fogheightpixel.a;\n"
1107 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1108 "#else\n"
1109 "# ifdef USEFOGOUTSIDE\n"
1110 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1111 "# else\n"
1112 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1113 "# endif\n"
1114 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1115 "#endif\n"
1116 "}\n"
1117 "#endif\n"
1118 "\n"
1119 "#ifdef USEOFFSETMAPPING\n"
1120 "uniform float OffsetMapping_Scale;\n"
1121 "vec2 OffsetMapping(vec2 TexCoord)\n"
1122 "{\n"
1123 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1124 "       // 14 sample relief mapping: linear search and then binary search\n"
1125 "       // this basically steps forward a small amount repeatedly until it finds\n"
1126 "       // itself inside solid, then jitters forward and back using decreasing\n"
1127 "       // amounts to find the impact\n"
1128 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1129 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1130 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1131 "       vec3 RT = vec3(TexCoord, 1);\n"
1132 "       OffsetVector *= 0.1;\n"
1133 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1134 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1135 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1136 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1137 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1138 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1139 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1140 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1141 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1142 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1143 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1144 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1145 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1146 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1147 "       return RT.xy;\n"
1148 "#else\n"
1149 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1150 "       // this basically moves forward the full distance, and then backs up based\n"
1151 "       // on height of samples\n"
1152 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1153 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1154 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1155 "       TexCoord += OffsetVector;\n"
1156 "       OffsetVector *= 0.5;\n"
1157 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1158 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1159 "       return TexCoord;\n"
1160 "#endif\n"
1161 "}\n"
1162 "#endif // USEOFFSETMAPPING\n"
1163 "\n"
1164 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1165 "uniform sampler2D Texture_Attenuation;\n"
1166 "uniform samplerCube Texture_Cube;\n"
1167 "#endif\n"
1168 "\n"
1169 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1170 "\n"
1171 "#ifdef USESHADOWMAPRECT\n"
1172 "# ifdef USESHADOWSAMPLER\n"
1173 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1174 "# else\n"
1175 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1176 "# endif\n"
1177 "#endif\n"
1178 "\n"
1179 "#ifdef USESHADOWMAP2D\n"
1180 "# ifdef USESHADOWSAMPLER\n"
1181 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1182 "# else\n"
1183 "uniform sampler2D Texture_ShadowMap2D;\n"
1184 "# endif\n"
1185 "#endif\n"
1186 "\n"
1187 "#ifdef USESHADOWMAPVSDCT\n"
1188 "uniform samplerCube Texture_CubeProjection;\n"
1189 "#endif\n"
1190 "\n"
1191 "#ifdef USESHADOWMAPCUBE\n"
1192 "# ifdef USESHADOWSAMPLER\n"
1193 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1194 "# else\n"
1195 "uniform samplerCube Texture_ShadowMapCube;\n"
1196 "# endif\n"
1197 "#endif\n"
1198 "\n"
1199 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1200 "uniform vec2 ShadowMap_TextureScale;\n"
1201 "uniform vec4 ShadowMap_Parameters;\n"
1202 "#endif\n"
1203 "\n"
1204 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1205 "# ifdef USESHADOWMAPORTHO\n"
1206 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1207 "# else\n"
1208 "#  ifdef USESHADOWMAPVSDCT\n"
1209 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1210 "{\n"
1211 "       vec3 adir = abs(dir);\n"
1212 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1213 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1214 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1215 "}\n"
1216 "#  else\n"
1217 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1218 "{\n"
1219 "       vec3 adir = abs(dir);\n"
1220 "       float ma = adir.z;\n"
1221 "       vec4 proj = vec4(dir, 2.5);\n"
1222 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1223 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1224 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1225 "       return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1226 "}\n"
1227 "#  endif\n"
1228 "# endif\n"
1229 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1230 "\n"
1231 "#ifdef USESHADOWMAPCUBE\n"
1232 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1233 "{\n"
1234 "       vec3 adir = abs(dir);\n"
1235 "       return vec4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
1236 "}\n"
1237 "#endif\n"
1238 "\n"
1239 "# ifdef USESHADOWMAPRECT\n"
1240 "float ShadowMapCompare(vec3 dir)\n"
1241 "{\n"
1242 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1243 "       float f;\n"
1244 "#  ifdef USESHADOWSAMPLER\n"
1245 "\n"
1246 "#    ifdef USESHADOWMAPPCF\n"
1247 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1248 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1249 "#    else\n"
1250 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1251 "#    endif\n"
1252 "\n"
1253 "#  else\n"
1254 "\n"
1255 "#    ifdef USESHADOWMAPPCF\n"
1256 "#      if USESHADOWMAPPCF > 1\n"
1257 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1258 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1259 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1260 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1261 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1262 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1263 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1264 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1265 "#      else\n"
1266 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1267 "       vec2 offset = fract(shadowmaptc.xy);\n"
1268 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1269 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1270 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1271 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1272 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1273 "#      endif\n"
1274 "#    else\n"
1275 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1276 "#    endif\n"
1277 "\n"
1278 "#  endif\n"
1279 "#  ifdef USESHADOWMAPORTHO\n"
1280 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1281 "#  else\n"
1282 "       return f;\n"
1283 "#  endif\n"
1284 "}\n"
1285 "# endif\n"
1286 "\n"
1287 "# ifdef USESHADOWMAP2D\n"
1288 "float ShadowMapCompare(vec3 dir)\n"
1289 "{\n"
1290 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1291 "       float f;\n"
1292 "\n"
1293 "#  ifdef USESHADOWSAMPLER\n"
1294 "#    ifdef USESHADOWMAPPCF\n"
1295 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1296 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1297 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1298 "#    else\n"
1299 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1300 "#    endif\n"
1301 "#  else\n"
1302 "#    ifdef USESHADOWMAPPCF\n"
1303 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1304 "#      ifdef GL_ARB_texture_gather\n"
1305 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1306 "#      else\n"
1307 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1308 "#      endif\n"
1309 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1310 "#      if USESHADOWMAPPCF > 1\n"
1311 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1312 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1313 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1314 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1315 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1316 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1317 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1318 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1319 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1320 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1321 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1322 "       locols.yz += group2.ab;\n"
1323 "       hicols.yz += group8.rg;\n"
1324 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1325 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1326 "                               mix(locols, hicols, offset.y);\n"
1327 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1328 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1329 "       f = dot(cols, vec4(1.0/25.0));\n"
1330 "#      else\n"
1331 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1332 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1333 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1334 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1335 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1336 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1337 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1338 "#      endif\n"
1339 "#     else\n"
1340 "#      ifdef GL_EXT_gpu_shader4\n"
1341 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1342 "#      else\n"
1343 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1344 "#      endif\n"
1345 "#      if USESHADOWMAPPCF > 1\n"
1346 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1347 "       center *= ShadowMap_TextureScale;\n"
1348 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1349 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1350 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1351 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1352 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1353 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1354 "#      else\n"
1355 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1356 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1357 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1358 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1359 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1360 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1361 "#      endif\n"
1362 "#     endif\n"
1363 "#    else\n"
1364 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1365 "#    endif\n"
1366 "#  endif\n"
1367 "#  ifdef USESHADOWMAPORTHO\n"
1368 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1369 "#  else\n"
1370 "       return f;\n"
1371 "#  endif\n"
1372 "}\n"
1373 "# endif\n"
1374 "\n"
1375 "# ifdef USESHADOWMAPCUBE\n"
1376 "float ShadowMapCompare(vec3 dir)\n"
1377 "{\n"
1378 "       // apply depth texture cubemap as light filter\n"
1379 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1380 "       float f;\n"
1381 "#  ifdef USESHADOWSAMPLER\n"
1382 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1383 "#  else\n"
1384 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1385 "#  endif\n"
1386 "       return f;\n"
1387 "}\n"
1388 "# endif\n"
1389 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1390 "#endif // FRAGMENT_SHADER\n"
1391 "\n"
1392 "\n"
1393 "\n"
1394 "\n"
1395 "#ifdef MODE_DEFERREDGEOMETRY\n"
1396 "#ifdef VERTEX_SHADER\n"
1397 "uniform mat4 TexMatrix;\n"
1398 "#ifdef USEVERTEXTEXTUREBLEND\n"
1399 "uniform mat4 BackgroundTexMatrix;\n"
1400 "#endif\n"
1401 "uniform mat4 ModelViewMatrix;\n"
1402 "void main(void)\n"
1403 "{\n"
1404 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1405 "#ifdef USEVERTEXTEXTUREBLEND\n"
1406 "       gl_FrontColor = gl_Color;\n"
1407 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1408 "#endif\n"
1409 "\n"
1410 "       // transform unnormalized eye direction into tangent space\n"
1411 "#ifdef USEOFFSETMAPPING\n"
1412 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1413 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1414 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1415 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1416 "#endif\n"
1417 "\n"
1418 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1419 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1420 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1421 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1422 "}\n"
1423 "#endif // VERTEX_SHADER\n"
1424 "\n"
1425 "#ifdef FRAGMENT_SHADER\n"
1426 "void main(void)\n"
1427 "{\n"
1428 "#ifdef USEOFFSETMAPPING\n"
1429 "       // apply offsetmapping\n"
1430 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1431 "#define TexCoord TexCoordOffset\n"
1432 "#endif\n"
1433 "\n"
1434 "#ifdef USEALPHAKILL\n"
1435 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1436 "               discard;\n"
1437 "#endif\n"
1438 "\n"
1439 "#ifdef USEVERTEXTEXTUREBLEND\n"
1440 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1441 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1442 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1443 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1444 "#endif\n"
1445 "\n"
1446 "#ifdef USEVERTEXTEXTUREBLEND\n"
1447 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1448 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1449 "#else\n"
1450 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1451 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1452 "#endif\n"
1453 "\n"
1454 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1455 "}\n"
1456 "#endif // FRAGMENT_SHADER\n"
1457 "#else // !MODE_DEFERREDGEOMETRY\n"
1458 "\n"
1459 "\n"
1460 "\n"
1461 "\n"
1462 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1463 "#ifdef VERTEX_SHADER\n"
1464 "uniform mat4 ModelViewMatrix;\n"
1465 "void main(void)\n"
1466 "{\n"
1467 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1468 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1469 "}\n"
1470 "#endif // VERTEX_SHADER\n"
1471 "\n"
1472 "#ifdef FRAGMENT_SHADER\n"
1473 "uniform mat4 ViewToLight;\n"
1474 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1475 "uniform vec2 ScreenToDepth;\n"
1476 "uniform myhalf3 DeferredColor_Ambient;\n"
1477 "uniform myhalf3 DeferredColor_Diffuse;\n"
1478 "#ifdef USESPECULAR\n"
1479 "uniform myhalf3 DeferredColor_Specular;\n"
1480 "uniform myhalf SpecularPower;\n"
1481 "#endif\n"
1482 "uniform myhalf2 PixelToScreenTexCoord;\n"
1483 "void main(void)\n"
1484 "{\n"
1485 "       // calculate viewspace pixel position\n"
1486 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1487 "       vec3 position;\n"
1488 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1489 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1490 "       // decode viewspace pixel normal\n"
1491 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1492 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1493 "       // surfacenormal = pixel normal in viewspace\n"
1494 "       // LightVector = pixel to light in viewspace\n"
1495 "       // CubeVector = position in lightspace\n"
1496 "       // eyevector = pixel to view in viewspace\n"
1497 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1498 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1499 "#ifdef USEDIFFUSE\n"
1500 "       // calculate diffuse shading\n"
1501 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1502 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1503 "#endif\n"
1504 "#ifdef USESPECULAR\n"
1505 "       // calculate directional shading\n"
1506 "       vec3 eyevector = position * -1.0;\n"
1507 "#  ifdef USEEXACTSPECULARMATH\n"
1508 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1509 "#  else\n"
1510 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1511 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1512 "#  endif\n"
1513 "#endif\n"
1514 "\n"
1515 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1516 "       fade *= ShadowMapCompare(CubeVector);\n"
1517 "#endif\n"
1518 "\n"
1519 "#ifdef USEDIFFUSE\n"
1520 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1521 "#else\n"
1522 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1523 "#endif\n"
1524 "#ifdef USESPECULAR\n"
1525 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1526 "#else\n"
1527 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1528 "#endif\n"
1529 "\n"
1530 "# ifdef USECUBEFILTER\n"
1531 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1532 "       gl_FragData[0].rgb *= cubecolor;\n"
1533 "       gl_FragData[1].rgb *= cubecolor;\n"
1534 "# endif\n"
1535 "}\n"
1536 "#endif // FRAGMENT_SHADER\n"
1537 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1538 "\n"
1539 "\n"
1540 "\n"
1541 "\n"
1542 "#ifdef VERTEX_SHADER\n"
1543 "uniform mat4 TexMatrix;\n"
1544 "#ifdef USEVERTEXTEXTUREBLEND\n"
1545 "uniform mat4 BackgroundTexMatrix;\n"
1546 "#endif\n"
1547 "#ifdef MODE_LIGHTSOURCE\n"
1548 "uniform mat4 ModelToLight;\n"
1549 "#endif\n"
1550 "#ifdef USESHADOWMAPORTHO\n"
1551 "uniform mat4 ShadowMapMatrix;\n"
1552 "#endif\n"
1553 "void main(void)\n"
1554 "{\n"
1555 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1556 "       gl_FrontColor = gl_Color;\n"
1557 "#endif\n"
1558 "       // copy the surface texcoord\n"
1559 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1560 "#ifdef USEVERTEXTEXTUREBLEND\n"
1561 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1562 "#endif\n"
1563 "#ifdef USELIGHTMAP\n"
1564 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1565 "#endif\n"
1566 "\n"
1567 "#ifdef MODE_LIGHTSOURCE\n"
1568 "       // transform vertex position into light attenuation/cubemap space\n"
1569 "       // (-1 to +1 across the light box)\n"
1570 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1571 "\n"
1572 "# ifdef USEDIFFUSE\n"
1573 "       // transform unnormalized light direction into tangent space\n"
1574 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1575 "       //  normalize it per pixel)\n"
1576 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1577 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1578 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1579 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1580 "# endif\n"
1581 "#endif\n"
1582 "\n"
1583 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1584 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1585 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1586 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1587 "#endif\n"
1588 "\n"
1589 "       // transform unnormalized eye direction into tangent space\n"
1590 "#ifdef USEEYEVECTOR\n"
1591 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1592 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1593 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1594 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1595 "#endif\n"
1596 "\n"
1597 "#ifdef USEFOG\n"
1598 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1599 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1600 "#endif\n"
1601 "\n"
1602 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1603 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1604 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1605 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1606 "#endif\n"
1607 "\n"
1608 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1609 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1610 "\n"
1611 "#ifdef USESHADOWMAPORTHO\n"
1612 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1613 "#endif\n"
1614 "\n"
1615 "#ifdef USEREFLECTION\n"
1616 "       ModelViewProjectionPosition = gl_Position;\n"
1617 "#endif\n"
1618 "}\n"
1619 "#endif // VERTEX_SHADER\n"
1620 "\n"
1621 "\n"
1622 "\n"
1623 "\n"
1624 "#ifdef FRAGMENT_SHADER\n"
1625 "#ifdef USEDEFERREDLIGHTMAP\n"
1626 "uniform myhalf2 PixelToScreenTexCoord;\n"
1627 "uniform myhalf3 DeferredMod_Diffuse;\n"
1628 "uniform myhalf3 DeferredMod_Specular;\n"
1629 "#endif\n"
1630 "uniform myhalf3 Color_Ambient;\n"
1631 "uniform myhalf3 Color_Diffuse;\n"
1632 "uniform myhalf3 Color_Specular;\n"
1633 "uniform myhalf SpecularPower;\n"
1634 "#ifdef USEGLOW\n"
1635 "uniform myhalf3 Color_Glow;\n"
1636 "#endif\n"
1637 "uniform myhalf Alpha;\n"
1638 "#ifdef USEREFLECTION\n"
1639 "uniform vec4 DistortScaleRefractReflect;\n"
1640 "uniform vec4 ScreenScaleRefractReflect;\n"
1641 "uniform vec4 ScreenCenterRefractReflect;\n"
1642 "uniform myhalf4 ReflectColor;\n"
1643 "#endif\n"
1644 "#ifdef USEREFLECTCUBE\n"
1645 "uniform mat4 ModelToReflectCube;\n"
1646 "uniform sampler2D Texture_ReflectMask;\n"
1647 "uniform samplerCube Texture_ReflectCube;\n"
1648 "#endif\n"
1649 "#ifdef MODE_LIGHTDIRECTION\n"
1650 "uniform myhalf3 LightColor;\n"
1651 "#endif\n"
1652 "#ifdef MODE_LIGHTSOURCE\n"
1653 "uniform myhalf3 LightColor;\n"
1654 "#endif\n"
1655 "void main(void)\n"
1656 "{\n"
1657 "#ifdef USEOFFSETMAPPING\n"
1658 "       // apply offsetmapping\n"
1659 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1660 "#define TexCoord TexCoordOffset\n"
1661 "#endif\n"
1662 "\n"
1663 "       // combine the diffuse textures (base, pants, shirt)\n"
1664 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1665 "#ifdef USEALPHAKILL\n"
1666 "       if (color.a < 0.5)\n"
1667 "               discard;\n"
1668 "#endif\n"
1669 "       color.a *= Alpha;\n"
1670 "#ifdef USECOLORMAPPING\n"
1671 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1672 "#endif\n"
1673 "#ifdef USEVERTEXTEXTUREBLEND\n"
1674 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1675 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1676 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1677 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1678 "       color.a = 1.0;\n"
1679 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1680 "#endif\n"
1681 "\n"
1682 "       // get the surface normal\n"
1683 "#ifdef USEVERTEXTEXTUREBLEND\n"
1684 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1685 "#else\n"
1686 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1687 "#endif\n"
1688 "\n"
1689 "       // get the material colors\n"
1690 "       myhalf3 diffusetex = color.rgb;\n"
1691 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1692 "# ifdef USEVERTEXTEXTUREBLEND\n"
1693 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1694 "# else\n"
1695 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1696 "# endif\n"
1697 "#endif\n"
1698 "\n"
1699 "#ifdef USEREFLECTCUBE\n"
1700 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1701 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1702 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1703 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1704 "#endif\n"
1705 "\n"
1706 "\n"
1707 "\n"
1708 "\n"
1709 "#ifdef MODE_LIGHTSOURCE\n"
1710 "       // light source\n"
1711 "#ifdef USEDIFFUSE\n"
1712 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1713 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1714 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1715 "#ifdef USESPECULAR\n"
1716 "#ifdef USEEXACTSPECULARMATH\n"
1717 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1718 "#else\n"
1719 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1720 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1721 "#endif\n"
1722 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1723 "#endif\n"
1724 "#else\n"
1725 "       color.rgb = diffusetex * Color_Ambient;\n"
1726 "#endif\n"
1727 "       color.rgb *= LightColor;\n"
1728 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1729 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1730 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1731 "#endif\n"
1732 "# ifdef USECUBEFILTER\n"
1733 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1734 "# endif\n"
1735 "#endif // MODE_LIGHTSOURCE\n"
1736 "\n"
1737 "\n"
1738 "\n"
1739 "\n"
1740 "#ifdef MODE_LIGHTDIRECTION\n"
1741 "#define SHADING\n"
1742 "#ifdef USEDIFFUSE\n"
1743 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1744 "#endif\n"
1745 "#define lightcolor LightColor\n"
1746 "#endif // MODE_LIGHTDIRECTION\n"
1747 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1748 "#define SHADING\n"
1749 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1750 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1751 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1752 "       // convert modelspace light vector to tangentspace\n"
1753 "       myhalf3 lightnormal;\n"
1754 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1755 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1756 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1757 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1758 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1759 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1760 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1761 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1762 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1763 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1764 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1765 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1766 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1767 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1768 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1769 "#define SHADING\n"
1770 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1771 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1772 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1773 "#endif\n"
1774 "\n"
1775 "\n"
1776 "\n"
1777 "\n"
1778 "#ifdef MODE_FAKELIGHT\n"
1779 "#define SHADING\n"
1780 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1781 "myhalf3 lightcolor = myhalf3(1.0);\n"
1782 "#endif // MODE_FAKELIGHT\n"
1783 "\n"
1784 "\n"
1785 "\n"
1786 "\n"
1787 "#ifdef MODE_LIGHTMAP\n"
1788 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1789 "#endif // MODE_LIGHTMAP\n"
1790 "#ifdef MODE_VERTEXCOLOR\n"
1791 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1792 "#endif // MODE_VERTEXCOLOR\n"
1793 "#ifdef MODE_FLATCOLOR\n"
1794 "       color.rgb = diffusetex * Color_Ambient;\n"
1795 "#endif // MODE_FLATCOLOR\n"
1796 "\n"
1797 "\n"
1798 "\n"
1799 "\n"
1800 "#ifdef SHADING\n"
1801 "# ifdef USEDIFFUSE\n"
1802 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1803 "#  ifdef USESPECULAR\n"
1804 "#   ifdef USEEXACTSPECULARMATH\n"
1805 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1806 "#   else\n"
1807 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1808 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1809 "#   endif\n"
1810 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1811 "#  else\n"
1812 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1813 "#  endif\n"
1814 "# else\n"
1815 "       color.rgb = diffusetex * Color_Ambient;\n"
1816 "# endif\n"
1817 "#endif\n"
1818 "\n"
1819 "#ifdef USESHADOWMAPORTHO\n"
1820 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1821 "#endif\n"
1822 "\n"
1823 "#ifdef USEDEFERREDLIGHTMAP\n"
1824 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1825 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1826 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1827 "#endif\n"
1828 "\n"
1829 "#ifdef USEGLOW\n"
1830 "#ifdef USEVERTEXTEXTUREBLEND\n"
1831 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1832 "#else\n"
1833 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1834 "#endif\n"
1835 "#endif\n"
1836 "\n"
1837 "#ifdef USEFOG\n"
1838 "       color.rgb = FogVertex(color.rgb);\n"
1839 "#endif\n"
1840 "\n"
1841 "       // 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"
1842 "#ifdef USEREFLECTION\n"
1843 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1844 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1845 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1846 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1847 "       // FIXME temporary hack to detect the case that the reflection\n"
1848 "       // gets blackened at edges due to leaving the area that contains actual\n"
1849 "       // content.\n"
1850 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1851 "       // 'appening.\n"
1852 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1853 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1854 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1855 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1856 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1857 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1858 "#endif\n"
1859 "\n"
1860 "       gl_FragColor = vec4(color);\n"
1861 "}\n"
1862 "#endif // FRAGMENT_SHADER\n"
1863 "\n"
1864 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1865 "#endif // !MODE_DEFERREDGEOMETRY\n"
1866 "#endif // !MODE_WATER\n"
1867 "#endif // !MODE_REFRACTION\n"
1868 "#endif // !MODE_BLOOMBLUR\n"
1869 "#endif // !MODE_GENERIC\n"
1870 "#endif // !MODE_POSTPROCESS\n"
1871 "#endif // !MODE_SHOWDEPTH\n"
1872 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1873 ;
1874
1875 /*
1876 =========================================================================================================================================================
1877
1878
1879
1880 =========================================================================================================================================================
1881
1882
1883
1884 =========================================================================================================================================================
1885
1886
1887
1888 =========================================================================================================================================================
1889
1890
1891
1892 =========================================================================================================================================================
1893
1894
1895
1896 =========================================================================================================================================================
1897
1898
1899
1900 =========================================================================================================================================================
1901 */
1902
1903 const char *builtincgshaderstring =
1904 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1905 "// written by Forest 'LordHavoc' Hale\n"
1906 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1907 "\n"
1908 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1909 "#if defined(USEREFLECTION)\n"
1910 "#undef USESHADOWMAPORTHO\n"
1911 "#endif\n"
1912 "\n"
1913 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1914 "# define USEFOG\n"
1915 "#endif\n"
1916 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1917 "#define USELIGHTMAP\n"
1918 "#endif\n"
1919 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1920 "#define USEEYEVECTOR\n"
1921 "#endif\n"
1922 "\n"
1923 "#ifdef FRAGMENT_SHADER\n"
1924 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1925 "#endif\n"
1926 "\n"
1927 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1928 "#ifdef VERTEX_SHADER\n"
1929 "void main\n"
1930 "(\n"
1931 "float4 gl_Vertex : POSITION,\n"
1932 "uniform float4x4 ModelViewProjectionMatrix,\n"
1933 "out float4 gl_Position : POSITION\n"
1934 ")\n"
1935 "{\n"
1936 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1937 "}\n"
1938 "#endif\n"
1939 "#else // !MODE_DEPTH_ORSHADOW\n"
1940 "\n"
1941 "\n"
1942 "\n"
1943 "\n"
1944 "#ifdef MODE_SHOWDEPTH\n"
1945 "#ifdef VERTEX_SHADER\n"
1946 "void main\n"
1947 "(\n"
1948 "float4 gl_Vertex : POSITION,\n"
1949 "uniform float4x4 ModelViewProjectionMatrix,\n"
1950 "out float4 gl_Position : POSITION,\n"
1951 "out float4 gl_FrontColor : COLOR0\n"
1952 ")\n"
1953 "{\n"
1954 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1955 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1956 "}\n"
1957 "#endif\n"
1958 "\n"
1959 "#ifdef FRAGMENT_SHADER\n"
1960 "void main\n"
1961 "(\n"
1962 "float4 gl_FrontColor : COLOR0,\n"
1963 "out float4 gl_FragColor : COLOR\n"
1964 ")\n"
1965 "{\n"
1966 "       gl_FragColor = gl_FrontColor;\n"
1967 "}\n"
1968 "#endif\n"
1969 "#else // !MODE_SHOWDEPTH\n"
1970 "\n"
1971 "\n"
1972 "\n"
1973 "\n"
1974 "#ifdef MODE_POSTPROCESS\n"
1975 "\n"
1976 "#ifdef VERTEX_SHADER\n"
1977 "void main\n"
1978 "(\n"
1979 "float4 gl_Vertex : POSITION,\n"
1980 "uniform float4x4 ModelViewProjectionMatrix,\n"
1981 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1982 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1983 "out float4 gl_Position : POSITION,\n"
1984 "out float2 TexCoord1 : TEXCOORD0,\n"
1985 "out float2 TexCoord2 : TEXCOORD1\n"
1986 ")\n"
1987 "{\n"
1988 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1989 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1990 "#ifdef USEBLOOM\n"
1991 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1992 "#endif\n"
1993 "}\n"
1994 "#endif\n"
1995 "\n"
1996 "#ifdef FRAGMENT_SHADER\n"
1997 "void main\n"
1998 "(\n"
1999 "float2 TexCoord1 : TEXCOORD0,\n"
2000 "float2 TexCoord2 : TEXCOORD1,\n"
2001 "uniform sampler2D Texture_First,\n"
2002 "#ifdef USEBLOOM\n"
2003 "uniform sampler2D Texture_Second,\n"
2004 "#endif\n"
2005 "#ifdef USEGAMMARAMPS\n"
2006 "uniform sampler2D Texture_GammaRamps,\n"
2007 "#endif\n"
2008 "#ifdef USESATURATION\n"
2009 "uniform float Saturation,\n"
2010 "#endif\n"
2011 "#ifdef USEVIEWTINT\n"
2012 "uniform float4 ViewTintColor,\n"
2013 "#endif\n"
2014 "uniform float4 UserVec1,\n"
2015 "uniform float4 UserVec2,\n"
2016 "uniform float4 UserVec3,\n"
2017 "uniform float4 UserVec4,\n"
2018 "uniform float ClientTime,\n"
2019 "uniform float2 PixelSize,\n"
2020 "out float4 gl_FragColor : COLOR\n"
2021 ")\n"
2022 "{\n"
2023 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
2024 "#ifdef USEBLOOM\n"
2025 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
2026 "#endif\n"
2027 "#ifdef USEVIEWTINT\n"
2028 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
2029 "#endif\n"
2030 "\n"
2031 "#ifdef USEPOSTPROCESSING\n"
2032 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
2033 "// 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"
2034 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2035 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2036 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2037 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2038 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2039 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
2040 "#endif\n"
2041 "\n"
2042 "#ifdef USESATURATION\n"
2043 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2044 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2045 "       // 'vampire sight' effect, wheres red is compensated\n"
2046 "       #ifdef SATURATION_REDCOMPENSATE\n"
2047 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2048 "               gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2049 "               gl_FragColor.r += r;\n"
2050 "       #else\n"
2051 "               // normal desaturation\n"
2052 "               //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2053 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2054 "       #endif\n"
2055 "#endif\n"
2056 "\n"
2057 "#ifdef USEGAMMARAMPS\n"
2058 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2059 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2060 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2061 "#endif\n"
2062 "}\n"
2063 "#endif\n"
2064 "#else // !MODE_POSTPROCESS\n"
2065 "\n"
2066 "\n"
2067 "\n"
2068 "\n"
2069 "#ifdef MODE_GENERIC\n"
2070 "#ifdef VERTEX_SHADER\n"
2071 "void main\n"
2072 "(\n"
2073 "float4 gl_Vertex : POSITION,\n"
2074 "uniform float4x4 ModelViewProjectionMatrix,\n"
2075 "float4 gl_Color : COLOR0,\n"
2076 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2077 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2078 "out float4 gl_Position : POSITION,\n"
2079 "out float4 gl_FrontColor : COLOR,\n"
2080 "out float2 TexCoord1 : TEXCOORD0,\n"
2081 "out float2 TexCoord2 : TEXCOORD1\n"
2082 ")\n"
2083 "{\n"
2084 "       gl_FrontColor = gl_Color;\n"
2085 "#ifdef USEDIFFUSE\n"
2086 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2087 "#endif\n"
2088 "#ifdef USESPECULAR\n"
2089 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2090 "#endif\n"
2091 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2092 "}\n"
2093 "#endif\n"
2094 "\n"
2095 "#ifdef FRAGMENT_SHADER\n"
2096 "\n"
2097 "void main\n"
2098 "(\n"
2099 "float4 gl_FrontColor : COLOR,\n"
2100 "float2 TexCoord1 : TEXCOORD0,\n"
2101 "float2 TexCoord2 : TEXCOORD1,\n"
2102 "#ifdef USEDIFFUSE\n"
2103 "uniform sampler2D Texture_First,\n"
2104 "#endif\n"
2105 "#ifdef USESPECULAR\n"
2106 "uniform sampler2D Texture_Second,\n"
2107 "#endif\n"
2108 "out float4 gl_FragColor : COLOR\n"
2109 ")\n"
2110 "{\n"
2111 "       gl_FragColor = gl_FrontColor;\n"
2112 "#ifdef USEDIFFUSE\n"
2113 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2114 "#endif\n"
2115 "\n"
2116 "#ifdef USESPECULAR\n"
2117 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2118 "# ifdef USECOLORMAPPING\n"
2119 "       gl_FragColor *= tex2;\n"
2120 "# endif\n"
2121 "# ifdef USEGLOW\n"
2122 "       gl_FragColor += tex2;\n"
2123 "# endif\n"
2124 "# ifdef USEVERTEXTEXTUREBLEND\n"
2125 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2126 "# endif\n"
2127 "#endif\n"
2128 "}\n"
2129 "#endif\n"
2130 "#else // !MODE_GENERIC\n"
2131 "\n"
2132 "\n"
2133 "\n"
2134 "\n"
2135 "#ifdef MODE_BLOOMBLUR\n"
2136 "#ifdef VERTEX_SHADER\n"
2137 "void main\n"
2138 "(\n"
2139 "float4 gl_Vertex : POSITION,\n"
2140 "uniform float4x4 ModelViewProjectionMatrix,\n"
2141 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2142 "out float4 gl_Position : POSITION,\n"
2143 "out float2 TexCoord : TEXCOORD0\n"
2144 ")\n"
2145 "{\n"
2146 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2147 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2148 "}\n"
2149 "#endif\n"
2150 "\n"
2151 "#ifdef FRAGMENT_SHADER\n"
2152 "\n"
2153 "void main\n"
2154 "(\n"
2155 "float2 TexCoord : TEXCOORD0,\n"
2156 "uniform sampler2D Texture_First,\n"
2157 "uniform float4 BloomBlur_Parameters,\n"
2158 "out float4 gl_FragColor : COLOR\n"
2159 ")\n"
2160 "{\n"
2161 "       int i;\n"
2162 "       float2 tc = TexCoord;\n"
2163 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2164 "       tc += BloomBlur_Parameters.xy;\n"
2165 "       for (i = 1;i < SAMPLES;i++)\n"
2166 "       {\n"
2167 "               color += tex2D(Texture_First, tc).rgb;\n"
2168 "               tc += BloomBlur_Parameters.xy;\n"
2169 "       }\n"
2170 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2171 "}\n"
2172 "#endif\n"
2173 "#else // !MODE_BLOOMBLUR\n"
2174 "#ifdef MODE_REFRACTION\n"
2175 "#ifdef VERTEX_SHADER\n"
2176 "void main\n"
2177 "(\n"
2178 "float4 gl_Vertex : POSITION,\n"
2179 "uniform float4x4 ModelViewProjectionMatrix,\n"
2180 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2181 "uniform float4x4 TexMatrix,\n"
2182 "uniform float3 EyePosition,\n"
2183 "out float4 gl_Position : POSITION,\n"
2184 "out float2 TexCoord : TEXCOORD0,\n"
2185 "out float3 EyeVector : TEXCOORD1,\n"
2186 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2187 ")\n"
2188 "{\n"
2189 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2190 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2191 "       ModelViewProjectionPosition = gl_Position;\n"
2192 "}\n"
2193 "#endif\n"
2194 "\n"
2195 "#ifdef FRAGMENT_SHADER\n"
2196 "void main\n"
2197 "(\n"
2198 "float2 TexCoord : TEXCOORD0,\n"
2199 "float3 EyeVector : TEXCOORD1,\n"
2200 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2201 "uniform sampler2D Texture_Normal,\n"
2202 "uniform sampler2D Texture_Refraction,\n"
2203 "uniform sampler2D Texture_Reflection,\n"
2204 "uniform float4 DistortScaleRefractReflect,\n"
2205 "uniform float4 ScreenScaleRefractReflect,\n"
2206 "uniform float4 ScreenCenterRefractReflect,\n"
2207 "uniform float4 RefractColor,\n"
2208 "out float4 gl_FragColor : COLOR\n"
2209 ")\n"
2210 "{\n"
2211 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2212 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2213 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2214 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2215 "       // FIXME temporary hack to detect the case that the reflection\n"
2216 "       // gets blackened at edges due to leaving the area that contains actual\n"
2217 "       // content.\n"
2218 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2219 "       // 'appening.\n"
2220 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2221 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2222 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2223 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2224 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2225 "       gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2226 "}\n"
2227 "#endif\n"
2228 "#else // !MODE_REFRACTION\n"
2229 "\n"
2230 "\n"
2231 "\n"
2232 "\n"
2233 "#ifdef MODE_WATER\n"
2234 "#ifdef VERTEX_SHADER\n"
2235 "\n"
2236 "void main\n"
2237 "(\n"
2238 "float4 gl_Vertex : POSITION,\n"
2239 "uniform float4x4 ModelViewProjectionMatrix,\n"
2240 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2241 "uniform float4x4 TexMatrix,\n"
2242 "uniform float3 EyePosition,\n"
2243 "out float4 gl_Position : POSITION,\n"
2244 "out float2 TexCoord : TEXCOORD0,\n"
2245 "out float3 EyeVector : TEXCOORD1,\n"
2246 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2247 ")\n"
2248 "{\n"
2249 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2250 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2251 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2252 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2253 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2254 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2255 "       ModelViewProjectionPosition = gl_Position;\n"
2256 "}\n"
2257 "#endif\n"
2258 "\n"
2259 "#ifdef FRAGMENT_SHADER\n"
2260 "void main\n"
2261 "(\n"
2262 "float2 TexCoord : TEXCOORD0,\n"
2263 "float3 EyeVector : TEXCOORD1,\n"
2264 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2265 "uniform sampler2D Texture_Normal,\n"
2266 "uniform sampler2D Texture_Refraction,\n"
2267 "uniform sampler2D Texture_Reflection,\n"
2268 "uniform float4 DistortScaleRefractReflect,\n"
2269 "uniform float4 ScreenScaleRefractReflect,\n"
2270 "uniform float4 ScreenCenterRefractReflect,\n"
2271 "uniform float4 RefractColor,\n"
2272 "uniform float4 ReflectColor,\n"
2273 "uniform float ReflectFactor,\n"
2274 "uniform float ReflectOffset,\n"
2275 "out float4 gl_FragColor : COLOR\n"
2276 ")\n"
2277 "{\n"
2278 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2279 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2280 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2281 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2282 "       // FIXME temporary hack to detect the case that the reflection\n"
2283 "       // gets blackened at edges due to leaving the area that contains actual\n"
2284 "       // content.\n"
2285 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2286 "       // 'appening.\n"
2287 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2288 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2289 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2290 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2291 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2292 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2293 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2294 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2295 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2296 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2297 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2298 "       gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2299 "}\n"
2300 "#endif\n"
2301 "#else // !MODE_WATER\n"
2302 "\n"
2303 "\n"
2304 "\n"
2305 "\n"
2306 "// 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"
2307 "\n"
2308 "// fragment shader specific:\n"
2309 "#ifdef FRAGMENT_SHADER\n"
2310 "\n"
2311 "#ifdef USEFOG\n"
2312 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask, sampler2D Texture_FogHeightTexture)\n"
2313 "{\n"
2314 "       float fogfrac;\n"
2315 "#ifdef USEFOGHEIGHTTEXTURE\n"
2316 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2317 "       fogfrac = fogheightpixel.a;\n"
2318 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2319 "#else\n"
2320 "# ifdef USEFOGOUTSIDE\n"
2321 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2322 "# else\n"
2323 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2324 "# endif\n"
2325 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2326 "#endif\n"
2327 "}\n"
2328 "#endif\n"
2329 "\n"
2330 "#ifdef USEOFFSETMAPPING\n"
2331 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2332 "{\n"
2333 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2334 "       // 14 sample relief mapping: linear search and then binary search\n"
2335 "       // this basically steps forward a small amount repeatedly until it finds\n"
2336 "       // itself inside solid, then jitters forward and back using decreasing\n"
2337 "       // amounts to find the impact\n"
2338 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2339 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2340 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2341 "       float3 RT = float3(TexCoord, 1);\n"
2342 "       OffsetVector *= 0.1;\n"
2343 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2344 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2345 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2346 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2347 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2348 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2349 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2350 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2351 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2352 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2353 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2354 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2355 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2356 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2357 "       return RT.xy;\n"
2358 "#else\n"
2359 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2360 "       // this basically moves forward the full distance, and then backs up based\n"
2361 "       // on height of samples\n"
2362 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2363 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2364 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2365 "       TexCoord += OffsetVector;\n"
2366 "       OffsetVector *= 0.333;\n"
2367 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2368 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2369 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2370 "       return TexCoord;\n"
2371 "#endif\n"
2372 "}\n"
2373 "#endif // USEOFFSETMAPPING\n"
2374 "\n"
2375 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2376 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2377 "# ifdef USESHADOWMAPORTHO\n"
2378 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2379 "# else\n"
2380 "#  ifdef USESHADOWMAPVSDCT\n"
2381 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2382 "{\n"
2383 "       float3 adir = abs(dir);\n"
2384 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2385 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2386 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2387 "}\n"
2388 "#  else\n"
2389 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2390 "{\n"
2391 "       float3 adir = abs(dir);\n"
2392 "       float ma = adir.z;\n"
2393 "       float4 proj = float4(dir, 2.5);\n"
2394 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2395 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2396 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2397 "       return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2398 "}\n"
2399 "#  endif\n"
2400 "# endif\n"
2401 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2402 "\n"
2403 "#ifdef USESHADOWMAPCUBE\n"
2404 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2405 "{\n"
2406 "    float3 adir = abs(dir);\n"
2407 "    return float4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
2408 "}\n"
2409 "#endif\n"
2410 "\n"
2411 "# ifdef USESHADOWMAPRECT\n"
2412 "#ifdef USESHADOWMAPVSDCT\n"
2413 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2414 "#else\n"
2415 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2416 "#endif\n"
2417 "{\n"
2418 "#ifdef USESHADOWMAPVSDCT\n"
2419 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2420 "#else\n"
2421 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2422 "#endif\n"
2423 "       float f;\n"
2424 "#  ifdef USESHADOWSAMPLER\n"
2425 "\n"
2426 "#    ifdef USESHADOWMAPPCF\n"
2427 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2428 "    f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2429 "#    else\n"
2430 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2431 "#    endif\n"
2432 "\n"
2433 "#  else\n"
2434 "\n"
2435 "#    ifdef USESHADOWMAPPCF\n"
2436 "#      if USESHADOWMAPPCF > 1\n"
2437 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2438 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2439 "    float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2440 "    float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2441 "    float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2442 "    float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2443 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2444 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2445 "#      else\n"
2446 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2447 "    float2 offset = frac(shadowmaptc.xy);\n"
2448 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2449 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2450 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2451 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2452 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2453 "#      endif\n"
2454 "#    else\n"
2455 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2456 "#    endif\n"
2457 "\n"
2458 "#  endif\n"
2459 "#  ifdef USESHADOWMAPORTHO\n"
2460 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2461 "#  else\n"
2462 "       return f;\n"
2463 "#  endif\n"
2464 "}\n"
2465 "# endif\n"
2466 "\n"
2467 "# ifdef USESHADOWMAP2D\n"
2468 "#ifdef USESHADOWMAPVSDCT\n"
2469 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2470 "#else\n"
2471 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2472 "#endif\n"
2473 "{\n"
2474 "#ifdef USESHADOWMAPVSDCT\n"
2475 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2476 "#else\n"
2477 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2478 "#endif\n"
2479 "    float f;\n"
2480 "\n"
2481 "#  ifdef USESHADOWSAMPLER\n"
2482 "#    ifdef USESHADOWMAPPCF\n"
2483 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2484 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2485 "    f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2486 "#    else\n"
2487 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2488 "#    endif\n"
2489 "#  else\n"
2490 "#    ifdef USESHADOWMAPPCF\n"
2491 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2492 "#      ifdef GL_ARB_texture_gather\n"
2493 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2494 "#      else\n"
2495 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2496 "#      endif\n"
2497 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2498 "    center *= ShadowMap_TextureScale;\n"
2499 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2500 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2501 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2502 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2503 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2504 "                lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2505 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2506 "#     else\n"
2507 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)  \n"
2508 "#      if USESHADOWMAPPCF > 1\n"
2509 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2510 "    center *= ShadowMap_TextureScale;\n"
2511 "    float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2512 "    float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2513 "    float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2514 "    float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2515 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2516 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2517 "#      else\n"
2518 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2519 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2520 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2521 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2522 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2523 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2524 "#      endif\n"
2525 "#     endif\n"
2526 "#    else\n"
2527 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2528 "#    endif\n"
2529 "#  endif\n"
2530 "#  ifdef USESHADOWMAPORTHO\n"
2531 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2532 "#  else\n"
2533 "       return f;\n"
2534 "#  endif\n"
2535 "}\n"
2536 "# endif\n"
2537 "\n"
2538 "# ifdef USESHADOWMAPCUBE\n"
2539 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2540 "{\n"
2541 "    // apply depth texture cubemap as light filter\n"
2542 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2543 "    float f;\n"
2544 "#  ifdef USESHADOWSAMPLER\n"
2545 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2546 "#  else\n"
2547 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2548 "#  endif\n"
2549 "    return f;\n"
2550 "}\n"
2551 "# endif\n"
2552 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2553 "#endif // FRAGMENT_SHADER\n"
2554 "\n"
2555 "\n"
2556 "\n"
2557 "\n"
2558 "#ifdef MODE_DEFERREDGEOMETRY\n"
2559 "#ifdef VERTEX_SHADER\n"
2560 "void main\n"
2561 "(\n"
2562 "float4 gl_Vertex : POSITION,\n"
2563 "uniform float4x4 ModelViewProjectionMatrix,\n"
2564 "#ifdef USEVERTEXTEXTUREBLEND\n"
2565 "float4 gl_Color : COLOR0,\n"
2566 "#endif\n"
2567 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2568 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2569 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2570 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2571 "uniform float4x4 TexMatrix,\n"
2572 "#ifdef USEVERTEXTEXTUREBLEND\n"
2573 "uniform float4x4 BackgroundTexMatrix,\n"
2574 "#endif\n"
2575 "uniform float4x4 ModelViewMatrix,\n"
2576 "#ifdef USEOFFSETMAPPING\n"
2577 "uniform float3 EyePosition,\n"
2578 "#endif\n"
2579 "out float4 gl_Position : POSITION,\n"
2580 "out float4 gl_FrontColor : COLOR,\n"
2581 "out float4 TexCoordBoth : TEXCOORD0,\n"
2582 "#ifdef USEOFFSETMAPPING\n"
2583 "out float3 EyeVector : TEXCOORD2,\n"
2584 "#endif\n"
2585 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2586 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2587 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2588 ")\n"
2589 "{\n"
2590 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2591 "#ifdef USEVERTEXTEXTUREBLEND\n"
2592 "       gl_FrontColor = gl_Color;\n"
2593 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2594 "#endif\n"
2595 "\n"
2596 "       // transform unnormalized eye direction into tangent space\n"
2597 "#ifdef USEOFFSETMAPPING\n"
2598 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2599 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2600 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2601 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2602 "#endif\n"
2603 "\n"
2604 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2605 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2606 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2607 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2608 "}\n"
2609 "#endif // VERTEX_SHADER\n"
2610 "\n"
2611 "#ifdef FRAGMENT_SHADER\n"
2612 "void main\n"
2613 "(\n"
2614 "float4 TexCoordBoth : TEXCOORD0,\n"
2615 "float3 EyeVector : TEXCOORD2,\n"
2616 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2617 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2618 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2619 "uniform sampler2D Texture_Normal,\n"
2620 "#ifdef USEALPHAKILL\n"
2621 "uniform sampler2D Texture_Color,\n"
2622 "#endif\n"
2623 "uniform sampler2D Texture_Gloss,\n"
2624 "#ifdef USEVERTEXTEXTUREBLEND\n"
2625 "uniform sampler2D Texture_SecondaryNormal,\n"
2626 "uniform sampler2D Texture_SecondaryGloss,\n"
2627 "#endif\n"
2628 "#ifdef USEOFFSETMAPPING\n"
2629 "uniform float OffsetMapping_Scale,\n"
2630 "#endif\n"
2631 "uniform half SpecularPower,\n"
2632 "out float4 gl_FragColor : COLOR\n"
2633 ")\n"
2634 "{\n"
2635 "       float2 TexCoord = TexCoordBoth.xy;\n"
2636 "#ifdef USEOFFSETMAPPING\n"
2637 "       // apply offsetmapping\n"
2638 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2639 "#define TexCoord TexCoordOffset\n"
2640 "#endif\n"
2641 "\n"
2642 "#ifdef USEALPHAKILL\n"
2643 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2644 "               discard;\n"
2645 "#endif\n"
2646 "\n"
2647 "#ifdef USEVERTEXTEXTUREBLEND\n"
2648 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2649 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2650 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2651 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2652 "#endif\n"
2653 "\n"
2654 "#ifdef USEVERTEXTEXTUREBLEND\n"
2655 "       float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2656 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2657 "#else\n"
2658 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2659 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2660 "#endif\n"
2661 "\n"
2662 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2663 "}\n"
2664 "#endif // FRAGMENT_SHADER\n"
2665 "#else // !MODE_DEFERREDGEOMETRY\n"
2666 "\n"
2667 "\n"
2668 "\n"
2669 "\n"
2670 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2671 "#ifdef VERTEX_SHADER\n"
2672 "void main\n"
2673 "(\n"
2674 "float4 gl_Vertex : POSITION,\n"
2675 "uniform float4x4 ModelViewProjectionMatrix,\n"
2676 "uniform float4x4 ModelViewMatrix,\n"
2677 "out float4 gl_Position : POSITION,\n"
2678 "out float4 ModelViewPosition : TEXCOORD0\n"
2679 ")\n"
2680 "{\n"
2681 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2682 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2683 "}\n"
2684 "#endif // VERTEX_SHADER\n"
2685 "\n"
2686 "#ifdef FRAGMENT_SHADER\n"
2687 "void main\n"
2688 "(\n"
2689 "float2 Pixel : WPOS,\n"
2690 "float4 ModelViewPosition : TEXCOORD0,\n"
2691 "uniform float4x4 ViewToLight,\n"
2692 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2693 "uniform float3 LightPosition,\n"
2694 "uniform half2 PixelToScreenTexCoord,\n"
2695 "uniform half3 DeferredColor_Ambient,\n"
2696 "uniform half3 DeferredColor_Diffuse,\n"
2697 "#ifdef USESPECULAR\n"
2698 "uniform half3 DeferredColor_Specular,\n"
2699 "uniform half SpecularPower,\n"
2700 "#endif\n"
2701 "uniform sampler2D Texture_Attenuation,\n"
2702 "uniform sampler2D Texture_ScreenDepth,\n"
2703 "uniform sampler2D Texture_ScreenNormalMap,\n"
2704 "\n"
2705 "#ifdef USECUBEFILTER\n"
2706 "uniform samplerCUBE Texture_Cube,\n"
2707 "#endif\n"
2708 "\n"
2709 "#ifdef USESHADOWMAPRECT\n"
2710 "# ifdef USESHADOWSAMPLER\n"
2711 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2712 "# else\n"
2713 "uniform samplerRECT Texture_ShadowMapRect,\n"
2714 "# endif\n"
2715 "#endif\n"
2716 "\n"
2717 "#ifdef USESHADOWMAP2D\n"
2718 "# ifdef USESHADOWSAMPLER\n"
2719 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2720 "# else\n"
2721 "uniform sampler2D Texture_ShadowMap2D,\n"
2722 "# endif\n"
2723 "#endif\n"
2724 "\n"
2725 "#ifdef USESHADOWMAPVSDCT\n"
2726 "uniform samplerCUBE Texture_CubeProjection,\n"
2727 "#endif\n"
2728 "\n"
2729 "#ifdef USESHADOWMAPCUBE\n"
2730 "# ifdef USESHADOWSAMPLER\n"
2731 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2732 "# else\n"
2733 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2734 "# endif\n"
2735 "#endif\n"
2736 "\n"
2737 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2738 "uniform float2 ShadowMap_TextureScale,\n"
2739 "uniform float4 ShadowMap_Parameters,\n"
2740 "#endif\n"
2741 "\n"
2742 "out float4 gl_FragData0 : COLOR0,\n"
2743 "out float4 gl_FragData1 : COLOR1\n"
2744 ")\n"
2745 "{\n"
2746 "       // calculate viewspace pixel position\n"
2747 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2748 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2749 "       float3 position;\n"
2750 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2751 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2752 "       // decode viewspace pixel normal\n"
2753 "       half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2754 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2755 "       // surfacenormal = pixel normal in viewspace\n"
2756 "       // LightVector = pixel to light in viewspace\n"
2757 "       // CubeVector = position in lightspace\n"
2758 "       // eyevector = pixel to view in viewspace\n"
2759 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2760 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2761 "#ifdef USEDIFFUSE\n"
2762 "       // calculate diffuse shading\n"
2763 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2764 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2765 "#endif\n"
2766 "#ifdef USESPECULAR\n"
2767 "       // calculate directional shading\n"
2768 "       float3 eyevector = position * -1.0;\n"
2769 "#  ifdef USEEXACTSPECULARMATH\n"
2770 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2771 "#  else\n"
2772 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2773 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2774 "#  endif\n"
2775 "#endif\n"
2776 "\n"
2777 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2778 "       fade *= ShadowMapCompare(CubeVector,\n"
2779 "# if defined(USESHADOWMAP2D)\n"
2780 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2781 "# endif\n"
2782 "# if defined(USESHADOWMAPRECT)\n"
2783 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2784 "# endif\n"
2785 "# if defined(USESHADOWMAPCUBE)\n"
2786 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2787 "# endif\n"
2788 "\n"
2789 "#ifdef USESHADOWMAPVSDCT\n"
2790 ", Texture_CubeProjection\n"
2791 "#endif\n"
2792 "       );\n"
2793 "#endif\n"
2794 "\n"
2795 "#ifdef USEDIFFUSE\n"
2796 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2797 "#else\n"
2798 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2799 "#endif\n"
2800 "#ifdef USESPECULAR\n"
2801 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2802 "#else\n"
2803 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2804 "#endif\n"
2805 "\n"
2806 "# ifdef USECUBEFILTER\n"
2807 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2808 "       gl_FragData0.rgb *= cubecolor;\n"
2809 "       gl_FragData1.rgb *= cubecolor;\n"
2810 "# endif\n"
2811 "}\n"
2812 "#endif // FRAGMENT_SHADER\n"
2813 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2814 "\n"
2815 "\n"
2816 "\n"
2817 "\n"
2818 "#ifdef VERTEX_SHADER\n"
2819 "void main\n"
2820 "(\n"
2821 "float4 gl_Vertex : POSITION,\n"
2822 "uniform float4x4 ModelViewProjectionMatrix,\n"
2823 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2824 "float4 gl_Color : COLOR0,\n"
2825 "#endif\n"
2826 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2827 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2828 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2829 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2830 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2831 "\n"
2832 "uniform float3 EyePosition,\n"
2833 "uniform float4x4 TexMatrix,\n"
2834 "#ifdef USEVERTEXTEXTUREBLEND\n"
2835 "uniform float4x4 BackgroundTexMatrix,\n"
2836 "#endif\n"
2837 "#ifdef MODE_LIGHTSOURCE\n"
2838 "uniform float4x4 ModelToLight,\n"
2839 "#endif\n"
2840 "#ifdef MODE_LIGHTSOURCE\n"
2841 "uniform float3 LightPosition,\n"
2842 "#endif\n"
2843 "#ifdef MODE_LIGHTDIRECTION\n"
2844 "uniform float3 LightDir,\n"
2845 "#endif\n"
2846 "uniform float4 FogPlane,\n"
2847 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2848 "uniform float3 LightPosition,\n"
2849 "#endif\n"
2850 "#ifdef USESHADOWMAPORTHO\n"
2851 "uniform float4x4 ShadowMapMatrix,\n"
2852 "#endif\n"
2853 "\n"
2854 "out float4 gl_FrontColor : COLOR,\n"
2855 "out float4 TexCoordBoth : TEXCOORD0,\n"
2856 "#ifdef USELIGHTMAP\n"
2857 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2858 "#endif\n"
2859 "#ifdef USEEYEVECTOR\n"
2860 "out float3 EyeVector : TEXCOORD2,\n"
2861 "#endif\n"
2862 "#ifdef USEREFLECTION\n"
2863 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2864 "#endif\n"
2865 "#ifdef USEFOG\n"
2866 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2867 "#endif\n"
2868 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2869 "out float3 LightVector : TEXCOORD1,\n"
2870 "#endif\n"
2871 "#ifdef MODE_LIGHTSOURCE\n"
2872 "out float3 CubeVector : TEXCOORD3,\n"
2873 "#endif\n"
2874 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2875 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2876 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2877 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2878 "#endif\n"
2879 "#ifdef USESHADOWMAPORTHO\n"
2880 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2881 "#endif\n"
2882 "out float4 gl_Position : POSITION\n"
2883 ")\n"
2884 "{\n"
2885 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2886 "       gl_FrontColor = gl_Color;\n"
2887 "#endif\n"
2888 "       // copy the surface texcoord\n"
2889 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2890 "#ifdef USEVERTEXTEXTUREBLEND\n"
2891 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2892 "#endif\n"
2893 "#ifdef USELIGHTMAP\n"
2894 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2895 "#endif\n"
2896 "\n"
2897 "#ifdef MODE_LIGHTSOURCE\n"
2898 "       // transform vertex position into light attenuation/cubemap space\n"
2899 "       // (-1 to +1 across the light box)\n"
2900 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2901 "\n"
2902 "# ifdef USEDIFFUSE\n"
2903 "       // transform unnormalized light direction into tangent space\n"
2904 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2905 "       //  normalize it per pixel)\n"
2906 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2907 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2908 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2909 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2910 "# endif\n"
2911 "#endif\n"
2912 "\n"
2913 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2914 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2915 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2916 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2917 "#endif\n"
2918 "\n"
2919 "       // transform unnormalized eye direction into tangent space\n"
2920 "#ifdef USEEYEVECTOR\n"
2921 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2922 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2923 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2924 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2925 "#endif\n"
2926 "\n"
2927 "#ifdef USEFOG\n"
2928 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2929 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2930 "#endif\n"
2931 "\n"
2932 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2933 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2934 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2935 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2936 "#endif\n"
2937 "\n"
2938 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2939 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2940 "\n"
2941 "#ifdef USESHADOWMAPORTHO\n"
2942 "       ShadowMapTC = float3(mul(ShadowMapMatrix, gl_Position));\n"
2943 "#endif\n"
2944 "\n"
2945 "#ifdef USEREFLECTION\n"
2946 "       ModelViewProjectionPosition = gl_Position;\n"
2947 "#endif\n"
2948 "}\n"
2949 "#endif // VERTEX_SHADER\n"
2950 "\n"
2951 "\n"
2952 "\n"
2953 "\n"
2954 "#ifdef FRAGMENT_SHADER\n"
2955 "void main\n"
2956 "(\n"
2957 "#ifdef USEDEFERREDLIGHTMAP\n"
2958 "float2 Pixel : WPOS,\n"
2959 "#endif\n"
2960 "float4 gl_FrontColor : COLOR,\n"
2961 "float4 TexCoordBoth : TEXCOORD0,\n"
2962 "#ifdef USELIGHTMAP\n"
2963 "float2 TexCoordLightmap : TEXCOORD1,\n"
2964 "#endif\n"
2965 "#ifdef USEEYEVECTOR\n"
2966 "float3 EyeVector : TEXCOORD2,\n"
2967 "#endif\n"
2968 "#ifdef USEREFLECTION\n"
2969 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2970 "#endif\n"
2971 "#ifdef USEFOG\n"
2972 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2973 "#endif\n"
2974 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2975 "float3 LightVector : TEXCOORD1,\n"
2976 "#endif\n"
2977 "#ifdef MODE_LIGHTSOURCE\n"
2978 "float3 CubeVector : TEXCOORD3,\n"
2979 "#endif\n"
2980 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2981 "float4 ModelViewPosition : TEXCOORD0,\n"
2982 "#endif\n"
2983 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2984 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2985 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2986 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2987 "#endif\n"
2988 "#ifdef USESHADOWMAPORTHO\n"
2989 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2990 "#endif\n"
2991 "\n"
2992 "uniform sampler2D Texture_Normal,\n"
2993 "uniform sampler2D Texture_Color,\n"
2994 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2995 "uniform sampler2D Texture_Gloss,\n"
2996 "#endif\n"
2997 "#ifdef USEGLOW\n"
2998 "uniform sampler2D Texture_Glow,\n"
2999 "#endif\n"
3000 "#ifdef USEVERTEXTEXTUREBLEND\n"
3001 "uniform sampler2D Texture_SecondaryNormal,\n"
3002 "uniform sampler2D Texture_SecondaryColor,\n"
3003 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3004 "uniform sampler2D Texture_SecondaryGloss,\n"
3005 "#endif\n"
3006 "#ifdef USEGLOW\n"
3007 "uniform sampler2D Texture_SecondaryGlow,\n"
3008 "#endif\n"
3009 "#endif\n"
3010 "#ifdef USECOLORMAPPING\n"
3011 "uniform sampler2D Texture_Pants,\n"
3012 "uniform sampler2D Texture_Shirt,\n"
3013 "#endif\n"
3014 "#ifdef USEFOG\n"
3015 "uniform sampler2D Texture_FogHeightTexture,\n"
3016 "uniform sampler2D Texture_FogMask,\n"
3017 "#endif\n"
3018 "#ifdef USELIGHTMAP\n"
3019 "uniform sampler2D Texture_Lightmap,\n"
3020 "#endif\n"
3021 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
3022 "uniform sampler2D Texture_Deluxemap,\n"
3023 "#endif\n"
3024 "#ifdef USEREFLECTION\n"
3025 "uniform sampler2D Texture_Reflection,\n"
3026 "#endif\n"
3027 "\n"
3028 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3029 "uniform sampler2D Texture_ScreenDepth,\n"
3030 "uniform sampler2D Texture_ScreenNormalMap,\n"
3031 "#endif\n"
3032 "#ifdef USEDEFERREDLIGHTMAP\n"
3033 "uniform sampler2D Texture_ScreenDiffuse,\n"
3034 "uniform sampler2D Texture_ScreenSpecular,\n"
3035 "#endif\n"
3036 "\n"
3037 "#ifdef USECOLORMAPPING\n"
3038 "uniform half3 Color_Pants,\n"
3039 "uniform half3 Color_Shirt,\n"
3040 "#endif\n"
3041 "#ifdef USEFOG\n"
3042 "uniform float3 FogColor,\n"
3043 "uniform float FogRangeRecip,\n"
3044 "uniform float FogPlaneViewDist,\n"
3045 "uniform float FogHeightFade,\n"
3046 "#endif\n"
3047 "\n"
3048 "#ifdef USEOFFSETMAPPING\n"
3049 "uniform float OffsetMapping_Scale,\n"
3050 "#endif\n"
3051 "\n"
3052 "#ifdef USEDEFERREDLIGHTMAP\n"
3053 "uniform half2 PixelToScreenTexCoord,\n"
3054 "uniform half3 DeferredMod_Diffuse,\n"
3055 "uniform half3 DeferredMod_Specular,\n"
3056 "#endif\n"
3057 "uniform half3 Color_Ambient,\n"
3058 "uniform half3 Color_Diffuse,\n"
3059 "uniform half3 Color_Specular,\n"
3060 "uniform half SpecularPower,\n"
3061 "#ifdef USEGLOW\n"
3062 "uniform half3 Color_Glow,\n"
3063 "#endif\n"
3064 "uniform half Alpha,\n"
3065 "#ifdef USEREFLECTION\n"
3066 "uniform float4 DistortScaleRefractReflect,\n"
3067 "uniform float4 ScreenScaleRefractReflect,\n"
3068 "uniform float4 ScreenCenterRefractReflect,\n"
3069 "uniform half4 ReflectColor,\n"
3070 "#endif\n"
3071 "#ifdef USEREFLECTCUBE\n"
3072 "uniform float4x4 ModelToReflectCube,\n"
3073 "uniform sampler2D Texture_ReflectMask,\n"
3074 "uniform samplerCUBE Texture_ReflectCube,\n"
3075 "#endif\n"
3076 "#ifdef MODE_LIGHTDIRECTION\n"
3077 "uniform half3 LightColor,\n"
3078 "#endif\n"
3079 "#ifdef MODE_LIGHTSOURCE\n"
3080 "uniform half3 LightColor,\n"
3081 "#endif\n"
3082 "\n"
3083 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3084 "uniform sampler2D Texture_Attenuation,\n"
3085 "uniform samplerCUBE Texture_Cube,\n"
3086 "#endif\n"
3087 "\n"
3088 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3089 "\n"
3090 "#ifdef USESHADOWMAPRECT\n"
3091 "# ifdef USESHADOWSAMPLER\n"
3092 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
3093 "# else\n"
3094 "uniform samplerRECT Texture_ShadowMapRect,\n"
3095 "# endif\n"
3096 "#endif\n"
3097 "\n"
3098 "#ifdef USESHADOWMAP2D\n"
3099 "# ifdef USESHADOWSAMPLER\n"
3100 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
3101 "# else\n"
3102 "uniform sampler2D Texture_ShadowMap2D,\n"
3103 "# endif\n"
3104 "#endif\n"
3105 "\n"
3106 "#ifdef USESHADOWMAPVSDCT\n"
3107 "uniform samplerCUBE Texture_CubeProjection,\n"
3108 "#endif\n"
3109 "\n"
3110 "#ifdef USESHADOWMAPCUBE\n"
3111 "# ifdef USESHADOWSAMPLER\n"
3112 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
3113 "# else\n"
3114 "uniform samplerCUBE Texture_ShadowMapCube,\n"
3115 "# endif\n"
3116 "#endif\n"
3117 "\n"
3118 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
3119 "uniform float2 ShadowMap_TextureScale,\n"
3120 "uniform float4 ShadowMap_Parameters,\n"
3121 "#endif\n"
3122 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3123 "\n"
3124 "out float4 gl_FragColor : COLOR\n"
3125 ")\n"
3126 "{\n"
3127 "       float2 TexCoord = TexCoordBoth.xy;\n"
3128 "#ifdef USEVERTEXTEXTUREBLEND\n"
3129 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3130 "#endif\n"
3131 "#ifdef USEOFFSETMAPPING\n"
3132 "       // apply offsetmapping\n"
3133 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3134 "#define TexCoord TexCoordOffset\n"
3135 "#endif\n"
3136 "\n"
3137 "       // combine the diffuse textures (base, pants, shirt)\n"
3138 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3139 "#ifdef USEALPHAKILL\n"
3140 "       if (color.a < 0.5)\n"
3141 "               discard;\n"
3142 "#endif\n"
3143 "       color.a *= Alpha;\n"
3144 "#ifdef USECOLORMAPPING\n"
3145 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
3146 "#endif\n"
3147 "#ifdef USEVERTEXTEXTUREBLEND\n"
3148 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3149 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3150 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3151 "       color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
3152 "       color.a = 1.0;\n"
3153 "       //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
3154 "#endif\n"
3155 "\n"
3156 "       // get the surface normal\n"
3157 "#ifdef USEVERTEXTEXTUREBLEND\n"
3158 "       half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3159 "#else\n"
3160 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
3161 "#endif\n"
3162 "\n"
3163 "       // get the material colors\n"
3164 "       half3 diffusetex = color.rgb;\n"
3165 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3166 "# ifdef USEVERTEXTEXTUREBLEND\n"
3167 "       half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
3168 "# else\n"
3169 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3170 "# endif\n"
3171 "#endif\n"
3172 "\n"
3173 "#ifdef USEREFLECTCUBE\n"
3174 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3175 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3176 "       float3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
3177 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord)) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord));\n"
3178 "#endif\n"
3179 "\n"
3180 "\n"
3181 "\n"
3182 "\n"
3183 "#ifdef MODE_LIGHTSOURCE\n"
3184 "       // light source\n"
3185 "#ifdef USEDIFFUSE\n"
3186 "       half3 lightnormal = half3(normalize(LightVector));\n"
3187 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3188 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3189 "#ifdef USESPECULAR\n"
3190 "#ifdef USEEXACTSPECULARMATH\n"
3191 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3192 "#else\n"
3193 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3194 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3195 "#endif\n"
3196 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3197 "#endif\n"
3198 "#else\n"
3199 "       color.rgb = diffusetex * Color_Ambient;\n"
3200 "#endif\n"
3201 "       color.rgb *= LightColor;\n"
3202 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
3203 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3204 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
3205 "# if defined(USESHADOWMAP2D)\n"
3206 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3207 "# endif\n"
3208 "# if defined(USESHADOWMAPRECT)\n"
3209 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3210 "# endif\n"
3211 "# if defined(USESHADOWMAPCUBE)\n"
3212 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3213 "# endif\n"
3214 "\n"
3215 "#ifdef USESHADOWMAPVSDCT\n"
3216 ", Texture_CubeProjection\n"
3217 "#endif\n"
3218 "       );\n"
3219 "\n"
3220 "#endif\n"
3221 "# ifdef USECUBEFILTER\n"
3222 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
3223 "# endif\n"
3224 "#endif // MODE_LIGHTSOURCE\n"
3225 "\n"
3226 "\n"
3227 "\n"
3228 "\n"
3229 "#ifdef MODE_LIGHTDIRECTION\n"
3230 "#define SHADING\n"
3231 "#ifdef USEDIFFUSE\n"
3232 "       half3 lightnormal = half3(normalize(LightVector));\n"
3233 "#endif\n"
3234 "#define lightcolor LightColor\n"
3235 "#endif // MODE_LIGHTDIRECTION\n"
3236 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3237 "#define SHADING\n"
3238 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3239 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3240 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3241 "       // convert modelspace light vector to tangentspace\n"
3242 "       half3 lightnormal;\n"
3243 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3244 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3245 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3246 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3247 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3248 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3249 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3250 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3251 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3252 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3253 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3254 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3255 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3256 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3257 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3258 "#define SHADING\n"
3259 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3260 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3261 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3262 "#endif\n"
3263 "\n"
3264 "\n"
3265 "\n"
3266 "\n"
3267 "#ifdef MODE_FAKELIGHT\n"
3268 "#define SHADING\n"
3269 "half3 lightnormal = half3(normalize(EyeVector));\n"
3270 "half3 lightcolor = half3(1.0);\n"
3271 "#endif // MODE_FAKELIGHT\n"
3272 "\n"
3273 "\n"
3274 "\n"
3275 "\n"
3276 "#ifdef MODE_LIGHTMAP\n"
3277 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3278 "#endif // MODE_LIGHTMAP\n"
3279 "#ifdef MODE_VERTEXCOLOR\n"
3280 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3281 "#endif // MODE_VERTEXCOLOR\n"
3282 "#ifdef MODE_FLATCOLOR\n"
3283 "       color.rgb = diffusetex * Color_Ambient;\n"
3284 "#endif // MODE_FLATCOLOR\n"
3285 "\n"
3286 "\n"
3287 "\n"
3288 "\n"
3289 "#ifdef SHADING\n"
3290 "# ifdef USEDIFFUSE\n"
3291 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3292 "#  ifdef USESPECULAR\n"
3293 "#   ifdef USEEXACTSPECULARMATH\n"
3294 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3295 "#   else\n"
3296 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3297 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3298 "#   endif\n"
3299 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3300 "#  else\n"
3301 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3302 "#  endif\n"
3303 "# else\n"
3304 "       color.rgb = diffusetex * Color_Ambient;\n"
3305 "# endif\n"
3306 "#endif\n"
3307 "\n"
3308 "#ifdef USESHADOWMAPORTHO\n"
3309 "       color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3310 "# if defined(USESHADOWMAP2D)\n"
3311 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3312 "# endif\n"
3313 "# if defined(USESHADOWMAPRECT)\n"
3314 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3315 "# endif\n"
3316 "       );\n"
3317 "#endif\n"
3318 "\n"
3319 "#ifdef USEDEFERREDLIGHTMAP\n"
3320 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3321 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3322 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3323 "#endif\n"
3324 "\n"
3325 "#ifdef USEGLOW\n"
3326 "#ifdef USEVERTEXTEXTUREBLEND\n"
3327 "       color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3328 "#else\n"
3329 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3330 "#endif\n"
3331 "#endif\n"
3332 "\n"
3333 "#ifdef USEFOG\n"
3334 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3335 "#endif\n"
3336 "\n"
3337 "       // 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"
3338 "#ifdef USEREFLECTION\n"
3339 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3340 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3341 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3342 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3343 "       // FIXME temporary hack to detect the case that the reflection\n"
3344 "       // gets blackened at edges due to leaving the area that contains actual\n"
3345 "       // content.\n"
3346 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3347 "       // 'appening.\n"
3348 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3349 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3350 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3351 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3352 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3353 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3354 "#endif\n"
3355 "\n"
3356 "       gl_FragColor = float4(color);\n"
3357 "}\n"
3358 "#endif // FRAGMENT_SHADER\n"
3359 "\n"
3360 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3361 "#endif // !MODE_DEFERREDGEOMETRY\n"
3362 "#endif // !MODE_WATER\n"
3363 "#endif // !MODE_REFRACTION\n"
3364 "#endif // !MODE_BLOOMBLUR\n"
3365 "#endif // !MODE_GENERIC\n"
3366 "#endif // !MODE_POSTPROCESS\n"
3367 "#endif // !MODE_SHOWDEPTH\n"
3368 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3369 ;
3370
3371 char *glslshaderstring = NULL;
3372 char *cgshaderstring = NULL;
3373
3374 //=======================================================================================================================================================
3375
3376 typedef struct shaderpermutationinfo_s
3377 {
3378         const char *pretext;
3379         const char *name;
3380 }
3381 shaderpermutationinfo_t;
3382
3383 typedef struct shadermodeinfo_s
3384 {
3385         const char *vertexfilename;
3386         const char *geometryfilename;
3387         const char *fragmentfilename;
3388         const char *pretext;
3389         const char *name;
3390 }
3391 shadermodeinfo_t;
3392
3393 typedef enum shaderpermutation_e
3394 {
3395         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3396         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3397         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3398         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3399         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3400         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3401         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3402         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3403         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3404         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3405         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3406         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3407         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3408         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3409         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3410         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3411         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3412         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3413         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3414         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3415         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3416         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3417         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3418         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3419         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<24, //< (lightsource) use orthographic shadowmap projection
3420         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<25, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3421         SHADERPERMUTATION_ALPHAKILL = 1<<26, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3422         SHADERPERMUTATION_REFLECTCUBE = 1<<27, ///< fake reflections using global cubemap (not HDRI light probe)
3423         SHADERPERMUTATION_NORMALMAPSCROLLBLEND = 1<<28, // (water) counter-direction normalmaps scrolling
3424         SHADERPERMUTATION_LIMIT = 1<<29, ///< size of permutations array
3425         SHADERPERMUTATION_COUNT = 29 ///< size of shaderpermutationinfo array
3426 }
3427 shaderpermutation_t;
3428
3429 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3430 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3431 {
3432         {"#define USEDIFFUSE\n", " diffuse"},
3433         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3434         {"#define USEVIEWTINT\n", " viewtint"},
3435         {"#define USECOLORMAPPING\n", " colormapping"},
3436         {"#define USESATURATION\n", " saturation"},
3437         {"#define USEFOGINSIDE\n", " foginside"},
3438         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3439         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3440         {"#define USEGAMMARAMPS\n", " gammaramps"},
3441         {"#define USECUBEFILTER\n", " cubefilter"},
3442         {"#define USEGLOW\n", " glow"},
3443         {"#define USEBLOOM\n", " bloom"},
3444         {"#define USESPECULAR\n", " specular"},
3445         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3446         {"#define USEREFLECTION\n", " reflection"},
3447         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3448         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3449         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3450         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3451         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3452         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3453         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3454         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3455         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3456         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3457         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3458         {"#define USEALPHAKILL\n", " alphakill"},
3459         {"#define USEREFLECTCUBE\n", " reflectcube"},
3460         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3461 };
3462
3463 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3464 typedef enum shadermode_e
3465 {
3466         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3467         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3468         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3469         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3470         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3471         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3472         SHADERMODE_FAKELIGHT, ///< (fakelight) modulate texture by "fake" lighting (no lightmaps, no nothing)
3473         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3474         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3475         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3476         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3477         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3478         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3479         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3480         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3481         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3482         SHADERMODE_COUNT
3483 }
3484 shadermode_t;
3485
3486 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3487 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3488 {
3489         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3490         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3491         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3492         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3493         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3494         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3495         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3496         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3497         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3498         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3499         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3500         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3501         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3502         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3503         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3504         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3505 };
3506
3507 #ifdef SUPPORTCG
3508 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3509 {
3510         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3511         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3512         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3513         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3514         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3515         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3516         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3517         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3518         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3519         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3520         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3521         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3522         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3523         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3524         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3525         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3526 };
3527 #endif
3528
3529 struct r_glsl_permutation_s;
3530 typedef struct r_glsl_permutation_s
3531 {
3532         /// hash lookup data
3533         struct r_glsl_permutation_s *hashnext;
3534         unsigned int mode;
3535         unsigned int permutation;
3536
3537         /// indicates if we have tried compiling this permutation already
3538         qboolean compiled;
3539         /// 0 if compilation failed
3540         int program;
3541         /// locations of detected uniforms in program object, or -1 if not found
3542         int loc_Texture_First;
3543         int loc_Texture_Second;
3544         int loc_Texture_GammaRamps;
3545         int loc_Texture_Normal;
3546         int loc_Texture_Color;
3547         int loc_Texture_Gloss;
3548         int loc_Texture_Glow;
3549         int loc_Texture_SecondaryNormal;
3550         int loc_Texture_SecondaryColor;
3551         int loc_Texture_SecondaryGloss;
3552         int loc_Texture_SecondaryGlow;
3553         int loc_Texture_Pants;
3554         int loc_Texture_Shirt;
3555         int loc_Texture_FogHeightTexture;
3556         int loc_Texture_FogMask;
3557         int loc_Texture_Lightmap;
3558         int loc_Texture_Deluxemap;
3559         int loc_Texture_Attenuation;
3560         int loc_Texture_Cube;
3561         int loc_Texture_Refraction;
3562         int loc_Texture_Reflection;
3563         int loc_Texture_ShadowMapRect;
3564         int loc_Texture_ShadowMapCube;
3565         int loc_Texture_ShadowMap2D;
3566         int loc_Texture_CubeProjection;
3567         int loc_Texture_ScreenDepth;
3568         int loc_Texture_ScreenNormalMap;
3569         int loc_Texture_ScreenDiffuse;
3570         int loc_Texture_ScreenSpecular;
3571         int loc_Texture_ReflectMask;
3572         int loc_Texture_ReflectCube;
3573         int loc_Alpha;
3574         int loc_BloomBlur_Parameters;
3575         int loc_ClientTime;
3576         int loc_Color_Ambient;
3577         int loc_Color_Diffuse;
3578         int loc_Color_Specular;
3579         int loc_Color_Glow;
3580         int loc_Color_Pants;
3581         int loc_Color_Shirt;
3582         int loc_DeferredColor_Ambient;
3583         int loc_DeferredColor_Diffuse;
3584         int loc_DeferredColor_Specular;
3585         int loc_DeferredMod_Diffuse;
3586         int loc_DeferredMod_Specular;
3587         int loc_DistortScaleRefractReflect;
3588         int loc_EyePosition;
3589         int loc_FogColor;
3590         int loc_FogHeightFade;
3591         int loc_FogPlane;
3592         int loc_FogPlaneViewDist;
3593         int loc_FogRangeRecip;
3594         int loc_LightColor;
3595         int loc_LightDir;
3596         int loc_LightPosition;
3597         int loc_OffsetMapping_Scale;
3598         int loc_PixelSize;
3599         int loc_ReflectColor;
3600         int loc_ReflectFactor;
3601         int loc_ReflectOffset;
3602         int loc_RefractColor;
3603         int loc_Saturation;
3604         int loc_ScreenCenterRefractReflect;
3605         int loc_ScreenScaleRefractReflect;
3606         int loc_ScreenToDepth;
3607         int loc_ShadowMap_Parameters;
3608         int loc_ShadowMap_TextureScale;
3609         int loc_SpecularPower;
3610         int loc_UserVec1;
3611         int loc_UserVec2;
3612         int loc_UserVec3;
3613         int loc_UserVec4;
3614         int loc_ViewTintColor;
3615         int loc_ViewToLight;
3616         int loc_ModelToLight;
3617         int loc_TexMatrix;
3618         int loc_BackgroundTexMatrix;
3619         int loc_ModelViewProjectionMatrix;
3620         int loc_ModelViewMatrix;
3621         int loc_PixelToScreenTexCoord;
3622         int loc_ModelToReflectCube;
3623         int loc_ShadowMapMatrix;        
3624         int loc_NormalmapScrollBlend;
3625 }
3626 r_glsl_permutation_t;
3627
3628 #define SHADERPERMUTATION_HASHSIZE 256
3629
3630
3631 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3632 // these can NOT degrade! only use for simple stuff
3633 enum
3634 {
3635         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3636         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3637         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3638         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3639         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3640         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
3641 };
3642 #define SHADERSTATICPARMS_COUNT 6
3643
3644 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3645 static int shaderstaticparms_count = 0;
3646
3647 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3648 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3649 qboolean R_CompileShader_CheckStaticParms(void)
3650 {
3651         static int r_compileshader_staticparms_save[1];
3652         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3653         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3654
3655         // detect all
3656         if (r_glsl_saturation_redcompensate.integer)
3657                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3658         if (r_shadow_glossexact.integer)
3659                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3660         if (r_glsl_postprocess.integer)
3661         {
3662                 if (r_glsl_postprocess_uservec1_enable.integer)
3663                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3664                 if (r_glsl_postprocess_uservec2_enable.integer)
3665                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3666                 if (r_glsl_postprocess_uservec3_enable.integer)
3667                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3668                 if (r_glsl_postprocess_uservec4_enable.integer)
3669                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3670         }
3671
3672         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3673 }
3674
3675 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3676         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3677                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3678         else \
3679                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3680 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3681 {
3682         shaderstaticparms_count = 0;
3683
3684         // emit all
3685         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3686         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3687         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3688         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3689         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3690         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3691 }
3692
3693 /// information about each possible shader permutation
3694 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3695 /// currently selected permutation
3696 r_glsl_permutation_t *r_glsl_permutation;
3697 /// storage for permutations linked in the hash table
3698 memexpandablearray_t r_glsl_permutationarray;
3699
3700 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3701 {
3702         //unsigned int hashdepth = 0;
3703         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3704         r_glsl_permutation_t *p;
3705         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3706         {
3707                 if (p->mode == mode && p->permutation == permutation)
3708                 {
3709                         //if (hashdepth > 10)
3710                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3711                         return p;
3712                 }
3713                 //hashdepth++;
3714         }
3715         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3716         p->mode = mode;
3717         p->permutation = permutation;
3718         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3719         r_glsl_permutationhash[mode][hashindex] = p;
3720         //if (hashdepth > 10)
3721         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3722         return p;
3723 }
3724
3725 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3726 {
3727         char *shaderstring;
3728         if (!filename || !filename[0])
3729                 return NULL;
3730         if (!strcmp(filename, "glsl/default.glsl"))
3731         {
3732                 if (!glslshaderstring)
3733                 {
3734                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3735                         if (glslshaderstring)
3736                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3737                         else
3738                                 glslshaderstring = (char *)builtinshaderstring;
3739                 }
3740                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3741                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3742                 return shaderstring;
3743         }
3744         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3745         if (shaderstring)
3746         {
3747                 if (printfromdisknotice)
3748                         Con_DPrintf("from disk %s... ", filename);
3749                 return shaderstring;
3750         }
3751         return shaderstring;
3752 }
3753
3754 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3755 {
3756         int i;
3757         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3758         char *vertexstring, *geometrystring, *fragmentstring;
3759         char permutationname[256];
3760         int vertstrings_count = 0;
3761         int geomstrings_count = 0;
3762         int fragstrings_count = 0;
3763         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3764         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3765         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3766
3767         if (p->compiled)
3768                 return;
3769         p->compiled = true;
3770         p->program = 0;
3771
3772         permutationname[0] = 0;
3773         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3774         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3775         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3776
3777         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3778
3779         // the first pretext is which type of shader to compile as
3780         // (later these will all be bound together as a program object)
3781         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3782         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3783         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3784
3785         // the second pretext is the mode (for example a light source)
3786         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3787         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3788         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3789         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3790
3791         // now add all the permutation pretexts
3792         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3793         {
3794                 if (permutation & (1<<i))
3795                 {
3796                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3797                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3798                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3799                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3800                 }
3801                 else
3802                 {
3803                         // keep line numbers correct
3804                         vertstrings_list[vertstrings_count++] = "\n";
3805                         geomstrings_list[geomstrings_count++] = "\n";
3806                         fragstrings_list[fragstrings_count++] = "\n";
3807                 }
3808         }
3809
3810         // add static parms
3811         R_CompileShader_AddStaticParms(mode, permutation);
3812         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3813         vertstrings_count += shaderstaticparms_count;
3814         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3815         geomstrings_count += shaderstaticparms_count;
3816         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3817         fragstrings_count += shaderstaticparms_count;
3818
3819         // now append the shader text itself
3820         vertstrings_list[vertstrings_count++] = vertexstring;
3821         geomstrings_list[geomstrings_count++] = geometrystring;
3822         fragstrings_list[fragstrings_count++] = fragmentstring;
3823
3824         // if any sources were NULL, clear the respective list
3825         if (!vertexstring)
3826                 vertstrings_count = 0;
3827         if (!geometrystring)
3828                 geomstrings_count = 0;
3829         if (!fragmentstring)
3830                 fragstrings_count = 0;
3831
3832         // compile the shader program
3833         if (vertstrings_count + geomstrings_count + fragstrings_count)
3834                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3835         if (p->program)
3836         {
3837                 CHECKGLERROR
3838                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3839                 // look up all the uniform variable names we care about, so we don't
3840                 // have to look them up every time we set them
3841
3842                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3843                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3844                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3845                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3846                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3847                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3848                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3849                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3850                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3851                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3852                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3853                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3854                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3855                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3856                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3857                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3858                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3859                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3860                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3861                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3862                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3863                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3864                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3865                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3866                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3867                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3868                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3869                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3870                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3871                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3872                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3873                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3874                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3875                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3876                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3877                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3878                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3879                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3880                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3881                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3882                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3883                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3884                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3885                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3886                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3887                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3888                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3889                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3890                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3891                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3892                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3893                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3894                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3895                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3896                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3897                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3898                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3899                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3900                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3901                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3902                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3903                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3904                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3905                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3906                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3907                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3908                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3909                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3910                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3911                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3912                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3913                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3914                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3915                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3916                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3917                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3918                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3919                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3920                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3921                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3922                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3923                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");            
3924                 p->loc_NormalmapScrollBlend       = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
3925                 // initialize the samplers to refer to the texture units we use
3926                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3927                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3928                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3929                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3930                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3931                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3932                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3933                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3934                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3935                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3936                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3937                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3938                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3939                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3940                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3941                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3942                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3943                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3944                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3945                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3946                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3947                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3948                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3949                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3950                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3951                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3952                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3953                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3954                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3955                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3956                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3957                 CHECKGLERROR
3958                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3959         }
3960         else
3961                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3962
3963         // free the strings
3964         if (vertexstring)
3965                 Mem_Free(vertexstring);
3966         if (geometrystring)
3967                 Mem_Free(geometrystring);
3968         if (fragmentstring)
3969                 Mem_Free(fragmentstring);
3970 }
3971
3972 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3973 {
3974         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3975         if (r_glsl_permutation != perm)
3976         {
3977                 r_glsl_permutation = perm;
3978                 if (!r_glsl_permutation->program)
3979                 {
3980                         if (!r_glsl_permutation->compiled)
3981                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3982                         if (!r_glsl_permutation->program)
3983                         {
3984                                 // remove features until we find a valid permutation
3985                                 int i;
3986                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3987                                 {
3988                                         // reduce i more quickly whenever it would not remove any bits
3989                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3990                                         if (!(permutation & j))
3991                                                 continue;
3992                                         permutation -= j;
3993                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3994                                         if (!r_glsl_permutation->compiled)
3995                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3996                                         if (r_glsl_permutation->program)
3997                                                 break;
3998                                 }
3999                                 if (i >= SHADERPERMUTATION_COUNT)
4000                                 {
4001                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4002                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4003                                         qglUseProgramObjectARB(0);CHECKGLERROR
4004                                         return; // no bit left to clear, entire mode is broken
4005                                 }
4006                         }
4007                 }
4008                 CHECKGLERROR
4009                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
4010         }
4011         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4012         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4013         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4014 }
4015
4016 #ifdef SUPPORTCG
4017 #include <Cg/cgGL.h>
4018 struct r_cg_permutation_s;
4019 typedef struct r_cg_permutation_s
4020 {
4021         /// hash lookup data
4022         struct r_cg_permutation_s *hashnext;
4023         unsigned int mode;
4024         unsigned int permutation;
4025
4026         /// indicates if we have tried compiling this permutation already
4027         qboolean compiled;
4028         /// 0 if compilation failed
4029         CGprogram vprogram;
4030         CGprogram fprogram;
4031         /// locations of detected parameters in programs, or NULL if not found
4032         CGparameter vp_EyePosition;
4033         CGparameter vp_FogPlane;
4034         CGparameter vp_LightDir;
4035         CGparameter vp_LightPosition;
4036         CGparameter vp_ModelToLight;
4037         CGparameter vp_TexMatrix;
4038         CGparameter vp_BackgroundTexMatrix;
4039         CGparameter vp_ModelViewProjectionMatrix;
4040         CGparameter vp_ModelViewMatrix;
4041         CGparameter vp_ShadowMapMatrix;
4042
4043         CGparameter fp_Texture_First;
4044         CGparameter fp_Texture_Second;
4045         CGparameter fp_Texture_GammaRamps;
4046         CGparameter fp_Texture_Normal;
4047         CGparameter fp_Texture_Color;
4048         CGparameter fp_Texture_Gloss;
4049         CGparameter fp_Texture_Glow;
4050         CGparameter fp_Texture_SecondaryNormal;
4051         CGparameter fp_Texture_SecondaryColor;
4052         CGparameter fp_Texture_SecondaryGloss;
4053         CGparameter fp_Texture_SecondaryGlow;
4054         CGparameter fp_Texture_Pants;
4055         CGparameter fp_Texture_Shirt;
4056         CGparameter fp_Texture_FogHeightTexture;
4057         CGparameter fp_Texture_FogMask;
4058         CGparameter fp_Texture_Lightmap;
4059         CGparameter fp_Texture_Deluxemap;
4060         CGparameter fp_Texture_Attenuation;
4061         CGparameter fp_Texture_Cube;
4062         CGparameter fp_Texture_Refraction;
4063         CGparameter fp_Texture_Reflection;
4064         CGparameter fp_Texture_ShadowMapRect;
4065         CGparameter fp_Texture_ShadowMapCube;
4066         CGparameter fp_Texture_ShadowMap2D;
4067         CGparameter fp_Texture_CubeProjection;
4068         CGparameter fp_Texture_ScreenDepth;
4069         CGparameter fp_Texture_ScreenNormalMap;
4070         CGparameter fp_Texture_ScreenDiffuse;
4071         CGparameter fp_Texture_ScreenSpecular;
4072         CGparameter fp_Texture_ReflectMask;
4073         CGparameter fp_Texture_ReflectCube;
4074         CGparameter fp_Alpha;
4075         CGparameter fp_BloomBlur_Parameters;
4076         CGparameter fp_ClientTime;
4077         CGparameter fp_Color_Ambient;
4078         CGparameter fp_Color_Diffuse;
4079         CGparameter fp_Color_Specular;
4080         CGparameter fp_Color_Glow;
4081         CGparameter fp_Color_Pants;
4082         CGparameter fp_Color_Shirt;
4083         CGparameter fp_DeferredColor_Ambient;
4084         CGparameter fp_DeferredColor_Diffuse;
4085         CGparameter fp_DeferredColor_Specular;
4086         CGparameter fp_DeferredMod_Diffuse;
4087         CGparameter fp_DeferredMod_Specular;
4088         CGparameter fp_DistortScaleRefractReflect;
4089         CGparameter fp_EyePosition;
4090         CGparameter fp_FogColor;
4091         CGparameter fp_FogHeightFade;
4092         CGparameter fp_FogPlane;
4093         CGparameter fp_FogPlaneViewDist;
4094         CGparameter fp_FogRangeRecip;
4095         CGparameter fp_LightColor;
4096         CGparameter fp_LightDir;
4097         CGparameter fp_LightPosition;
4098         CGparameter fp_OffsetMapping_Scale;
4099         CGparameter fp_PixelSize;
4100         CGparameter fp_ReflectColor;
4101         CGparameter fp_ReflectFactor;
4102         CGparameter fp_ReflectOffset;
4103         CGparameter fp_RefractColor;
4104         CGparameter fp_Saturation;
4105         CGparameter fp_ScreenCenterRefractReflect;
4106         CGparameter fp_ScreenScaleRefractReflect;
4107         CGparameter fp_ScreenToDepth;
4108         CGparameter fp_ShadowMap_Parameters;
4109         CGparameter fp_ShadowMap_TextureScale;
4110         CGparameter fp_SpecularPower;
4111         CGparameter fp_UserVec1;
4112         CGparameter fp_UserVec2;
4113         CGparameter fp_UserVec3;
4114         CGparameter fp_UserVec4;
4115         CGparameter fp_ViewTintColor;
4116         CGparameter fp_ViewToLight;
4117         CGparameter fp_PixelToScreenTexCoord;
4118         CGparameter fp_ModelToReflectCube;
4119         CGparameter fp_NormalmapScrollBlend;
4120 }
4121 r_cg_permutation_t;
4122
4123 /// information about each possible shader permutation
4124 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4125 /// currently selected permutation
4126 r_cg_permutation_t *r_cg_permutation;
4127 /// storage for permutations linked in the hash table
4128 memexpandablearray_t r_cg_permutationarray;
4129
4130 #define CHECKCGERROR {CGerror err = cgGetError(), err2 = err;if (err){Con_Printf("%s:%i CG error %i: %s : %s\n", __FILE__, __LINE__, err, cgGetErrorString(err), cgGetLastErrorString(&err2));if (err == 1) Con_Printf("last listing:\n%s\n", cgGetLastListing(vid.cgcontext));}}
4131
4132 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4133 {
4134         //unsigned int hashdepth = 0;
4135         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4136         r_cg_permutation_t *p;
4137         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4138         {
4139                 if (p->mode == mode && p->permutation == permutation)
4140                 {
4141                         //if (hashdepth > 10)
4142                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4143                         return p;
4144                 }
4145                 //hashdepth++;
4146         }
4147         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4148         p->mode = mode;
4149         p->permutation = permutation;
4150         p->hashnext = r_cg_permutationhash[mode][hashindex];
4151         r_cg_permutationhash[mode][hashindex] = p;
4152         //if (hashdepth > 10)
4153         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4154         return p;
4155 }
4156
4157 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4158 {
4159         char *shaderstring;
4160         if (!filename || !filename[0])
4161                 return NULL;
4162         if (!strcmp(filename, "cg/default.cg"))
4163         {
4164                 if (!cgshaderstring)
4165                 {
4166                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4167                         if (cgshaderstring)
4168                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4169                         else
4170                                 cgshaderstring = (char *)builtincgshaderstring;
4171                 }
4172                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4173                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4174                 return shaderstring;
4175         }
4176         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4177         if (shaderstring)
4178         {
4179                 if (printfromdisknotice)
4180                         Con_DPrintf("from disk %s... ", filename);
4181                 return shaderstring;
4182         }
4183         return shaderstring;
4184 }
4185
4186 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4187 {
4188         // TODO: load or create .fp and .vp shader files
4189 }
4190
4191 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4192 {
4193         int i;
4194         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4195         int vertstring_length = 0;
4196         int geomstring_length = 0;
4197         int fragstring_length = 0;
4198         char *t;
4199         char *vertexstring, *geometrystring, *fragmentstring;
4200         char *vertstring, *geomstring, *fragstring;
4201         char permutationname[256];
4202         char cachename[256];
4203         CGprofile vertexProfile;
4204         CGprofile fragmentProfile;
4205         int vertstrings_count = 0;
4206         int geomstrings_count = 0;
4207         int fragstrings_count = 0;
4208         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4209         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4210         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4211
4212         if (p->compiled)
4213                 return;
4214         p->compiled = true;
4215         p->vprogram = NULL;
4216         p->fprogram = NULL;
4217
4218         permutationname[0] = 0;
4219         cachename[0] = 0;
4220         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4221         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4222         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4223
4224         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4225         strlcat(cachename, "cg/", sizeof(cachename));
4226
4227         // the first pretext is which type of shader to compile as
4228         // (later these will all be bound together as a program object)
4229         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4230         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4231         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4232
4233         // the second pretext is the mode (for example a light source)
4234         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4235         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4236         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4237         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4238         strlcat(cachename, modeinfo->name, sizeof(cachename));
4239
4240         // now add all the permutation pretexts
4241         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4242         {
4243                 if (permutation & (1<<i))
4244                 {
4245                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4246                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4247                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4248                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4249                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4250                 }
4251                 else
4252                 {
4253                         // keep line numbers correct
4254                         vertstrings_list[vertstrings_count++] = "\n";
4255                         geomstrings_list[geomstrings_count++] = "\n";
4256                         fragstrings_list[fragstrings_count++] = "\n";
4257                 }
4258         }
4259
4260         // add static parms
4261         R_CompileShader_AddStaticParms(mode, permutation);
4262         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4263         vertstrings_count += shaderstaticparms_count;
4264         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4265         geomstrings_count += shaderstaticparms_count;
4266         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4267         fragstrings_count += shaderstaticparms_count;
4268
4269         // replace spaces in the cachename with _ characters
4270         for (i = 0;cachename[i];i++)
4271                 if (cachename[i] == ' ')
4272                         cachename[i] = '_';
4273
4274         // now append the shader text itself
4275         vertstrings_list[vertstrings_count++] = vertexstring;
4276         geomstrings_list[geomstrings_count++] = geometrystring;
4277         fragstrings_list[fragstrings_count++] = fragmentstring;
4278
4279         // if any sources were NULL, clear the respective list
4280         if (!vertexstring)
4281                 vertstrings_count = 0;
4282         if (!geometrystring)
4283                 geomstrings_count = 0;
4284         if (!fragmentstring)
4285                 fragstrings_count = 0;
4286
4287         vertstring_length = 0;
4288         for (i = 0;i < vertstrings_count;i++)
4289                 vertstring_length += strlen(vertstrings_list[i]);
4290         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4291         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4292                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4293
4294         geomstring_length = 0;
4295         for (i = 0;i < geomstrings_count;i++)
4296                 geomstring_length += strlen(geomstrings_list[i]);
4297         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4298         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4299                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4300
4301         fragstring_length = 0;
4302         for (i = 0;i < fragstrings_count;i++)
4303                 fragstring_length += strlen(fragstrings_list[i]);
4304         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4305         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4306                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4307
4308         CHECKGLERROR
4309         CHECKCGERROR
4310         //vertexProfile = CG_PROFILE_ARBVP1;
4311         //fragmentProfile = CG_PROFILE_ARBFP1;
4312         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4313         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4314         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4315         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4316         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4317         CHECKGLERROR
4318
4319         // try to load the cached shader, or generate one
4320         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4321
4322         // if caching failed, do a dynamic compile for now
4323         CHECKCGERROR
4324         if (vertstring[0] && !p->vprogram)
4325                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4326         CHECKCGERROR
4327         if (fragstring[0] && !p->fprogram)
4328                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4329         CHECKCGERROR
4330
4331         // look up all the uniform variable names we care about, so we don't
4332         // have to look them up every time we set them
4333         if (p->vprogram)
4334         {
4335                 CHECKCGERROR
4336                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4337                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4338                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4339                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4340                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4341                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4342                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4343                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4344                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4345                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4346                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4347                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4348                 CHECKCGERROR
4349         }
4350         if (p->fprogram)
4351         {
4352                 CHECKCGERROR
4353                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4354                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4355                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4356                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4357                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4358                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4359                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4360                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4361                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4362                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4363                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4364                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4365                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4366                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4367                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4368                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4369                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4370                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4371                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4372                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4373                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4374                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4375                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4376                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4377                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4378                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4379                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4380                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4381                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4382                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4383                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4384                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4385                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4386                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4387                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4388                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4389                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4390                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4391                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4392                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4393                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4394                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4395                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4396                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4397                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4398                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4399                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4400                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4401                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4402                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4403                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4404                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4405                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4406                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4407                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4408                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4409                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4410                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4411                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4412                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4413                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4414                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4415                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4416                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4417                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4418                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4419                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4420                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4421                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4422                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4423                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4424                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4425                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4426                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4427                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4428                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4429                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4430                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4431                 p->fp_NormalmapScrollBlend       = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4432                 CHECKCGERROR
4433         }
4434
4435         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4436                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4437         else
4438                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4439
4440         // free the strings
4441         if (vertstring)
4442                 Mem_Free(vertstring);
4443         if (geomstring)
4444                 Mem_Free(geomstring);
4445         if (fragstring)
4446                 Mem_Free(fragstring);
4447         if (vertexstring)
4448                 Mem_Free(vertexstring);
4449         if (geometrystring)
4450                 Mem_Free(geometrystring);
4451         if (fragmentstring)
4452                 Mem_Free(fragmentstring);
4453 }
4454
4455 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4456 {
4457         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4458         CHECKGLERROR
4459         CHECKCGERROR
4460         if (r_cg_permutation != perm)
4461         {
4462                 r_cg_permutation = perm;
4463                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4464                 {
4465                         if (!r_cg_permutation->compiled)
4466                                 R_CG_CompilePermutation(perm, mode, permutation);
4467                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4468                         {
4469                                 // remove features until we find a valid permutation
4470                                 int i;
4471                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4472                                 {
4473                                         // reduce i more quickly whenever it would not remove any bits
4474                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4475                                         if (!(permutation & j))
4476                                                 continue;
4477                                         permutation -= j;
4478                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4479                                         if (!r_cg_permutation->compiled)
4480                                                 R_CG_CompilePermutation(perm, mode, permutation);
4481                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4482                                                 break;
4483                                 }
4484                                 if (i >= SHADERPERMUTATION_COUNT)
4485                                 {
4486                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4487                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4488                                         return; // no bit left to clear, entire mode is broken
4489                                 }
4490                         }
4491                 }
4492                 CHECKGLERROR
4493                 CHECKCGERROR
4494                 if (r_cg_permutation->vprogram)
4495                 {
4496                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4497                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4498                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4499                 }
4500                 else
4501                 {
4502                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4503                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4504                 }
4505                 if (r_cg_permutation->fprogram)
4506                 {
4507                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4508                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4509                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4510                 }
4511                 else
4512                 {
4513                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4514                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4515                 }
4516         }
4517         CHECKCGERROR
4518         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4519         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4520         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4521 }
4522
4523 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4524 {
4525         cgGLSetTextureParameter(param, R_GetTexture(tex));
4526         cgGLEnableTextureParameter(param);
4527 }
4528 #endif
4529
4530 void R_GLSL_Restart_f(void)
4531 {
4532         unsigned int i, limit;
4533         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4534                 Mem_Free(glslshaderstring);
4535         glslshaderstring = NULL;
4536         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4537                 Mem_Free(cgshaderstring);
4538         cgshaderstring = NULL;
4539         switch(vid.renderpath)
4540         {
4541         case RENDERPATH_GL20:
4542                 {
4543                         r_glsl_permutation_t *p;
4544                         r_glsl_permutation = NULL;
4545                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4546                         for (i = 0;i < limit;i++)
4547                         {
4548                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4549                                 {
4550                                         GL_Backend_FreeProgram(p->program);
4551                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4552                                 }
4553                         }
4554                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4555                 }
4556                 break;
4557         case RENDERPATH_CGGL:
4558 #ifdef SUPPORTCG
4559                 {
4560                         r_cg_permutation_t *p;
4561                         r_cg_permutation = NULL;
4562                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4563                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4564                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4565                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4566                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4567                         for (i = 0;i < limit;i++)
4568                         {
4569                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4570                                 {
4571                                         if (p->vprogram)
4572                                                 cgDestroyProgram(p->vprogram);
4573                                         if (p->fprogram)
4574                                                 cgDestroyProgram(p->fprogram);
4575                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4576                                 }
4577                         }
4578                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4579                 }
4580                 break;
4581 #endif
4582         case RENDERPATH_GL13:
4583         case RENDERPATH_GL11:
4584                 break;
4585         }
4586 }
4587
4588 void R_GLSL_DumpShader_f(void)
4589 {
4590         int i;
4591         qfile_t *file;
4592
4593         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4594         if (file)
4595         {
4596                 FS_Print(file, "/* The engine may define the following macros:\n");
4597                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4598                 for (i = 0;i < SHADERMODE_COUNT;i++)
4599                         FS_Print(file, glslshadermodeinfo[i].pretext);
4600                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4601                         FS_Print(file, shaderpermutationinfo[i].pretext);
4602                 FS_Print(file, "*/\n");
4603                 FS_Print(file, builtinshaderstring);
4604                 FS_Close(file);
4605                 Con_Printf("glsl/default.glsl written\n");
4606         }
4607         else
4608                 Con_Printf("failed to write to glsl/default.glsl\n");
4609
4610 #ifdef SUPPORTCG
4611         file = FS_OpenRealFile("cg/default.cg", "w", false);
4612         if (file)
4613         {
4614                 FS_Print(file, "/* The engine may define the following macros:\n");
4615                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4616                 for (i = 0;i < SHADERMODE_COUNT;i++)
4617                         FS_Print(file, cgshadermodeinfo[i].pretext);
4618                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4619                         FS_Print(file, shaderpermutationinfo[i].pretext);
4620                 FS_Print(file, "*/\n");
4621                 FS_Print(file, builtincgshaderstring);
4622                 FS_Close(file);
4623                 Con_Printf("cg/default.cg written\n");
4624         }
4625         else
4626                 Con_Printf("failed to write to cg/default.cg\n");
4627 #endif
4628 }
4629
4630 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4631 {
4632         if (!second)
4633                 texturemode = GL_MODULATE;
4634         switch (vid.renderpath)
4635         {
4636         case RENDERPATH_GL20:
4637                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
4638                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4639                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4640                 break;
4641         case RENDERPATH_CGGL:
4642 #ifdef SUPPORTCG
4643                 CHECKCGERROR
4644                 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
4645                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4646                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4647 #endif
4648                 break;
4649         case RENDERPATH_GL13:
4650                 R_Mesh_TexBind(0, first );
4651                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4652                 R_Mesh_TexBind(1, second);
4653                 if (second)
4654                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4655                 break;
4656         case RENDERPATH_GL11:
4657                 R_Mesh_TexBind(0, first );
4658                 break;
4659         }
4660 }
4661
4662 void R_SetupShader_DepthOrShadow(void)
4663 {
4664         switch (vid.renderpath)
4665         {
4666         case RENDERPATH_GL20:
4667                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4668                 break;
4669         case RENDERPATH_CGGL:
4670 #ifdef SUPPORTCG
4671                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4672 #endif
4673                 break;
4674         case RENDERPATH_GL13:
4675                 R_Mesh_TexBind(0, 0);
4676                 R_Mesh_TexBind(1, 0);
4677                 break;
4678         case RENDERPATH_GL11:
4679                 R_Mesh_TexBind(0, 0);
4680                 break;
4681         }
4682 }
4683
4684 void R_SetupShader_ShowDepth(void)
4685 {
4686         switch (vid.renderpath)
4687         {
4688         case RENDERPATH_GL20:
4689                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4690                 break;
4691         case RENDERPATH_CGGL:
4692 #ifdef SUPPORTCG
4693                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4694 #endif
4695                 break;
4696         case RENDERPATH_GL13:
4697                 break;
4698         case RENDERPATH_GL11:
4699                 break;
4700         }
4701 }
4702
4703 extern qboolean r_shadow_usingdeferredprepass;
4704 extern cvar_t r_shadow_deferred_8bitrange;
4705 extern rtexture_t *r_shadow_attenuationgradienttexture;
4706 extern rtexture_t *r_shadow_attenuation2dtexture;
4707 extern rtexture_t *r_shadow_attenuation3dtexture;
4708 extern qboolean r_shadow_usingshadowmaprect;
4709 extern qboolean r_shadow_usingshadowmapcube;
4710 extern qboolean r_shadow_usingshadowmap2d;
4711 extern qboolean r_shadow_usingshadowmaportho;
4712 extern float r_shadow_shadowmap_texturescale[2];
4713 extern float r_shadow_shadowmap_parameters[4];
4714 extern qboolean r_shadow_shadowmapvsdct;
4715 extern qboolean r_shadow_shadowmapsampler;
4716 extern int r_shadow_shadowmappcf;
4717 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4718 extern rtexture_t *r_shadow_shadowmap2dtexture;
4719 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4720 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4721 extern matrix4x4_t r_shadow_shadowmapmatrix;
4722 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4723 extern int r_shadow_prepass_width;
4724 extern int r_shadow_prepass_height;
4725 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4726 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4727 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4728 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4729 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
4730 {
4731         // a blendfunc allows colormod if:
4732         // a) it can never keep the destination pixel invariant, or
4733         // b) it can keep the destination pixel invariant, and still can do so if colormodded
4734         // this is to prevent unintended side effects from colormod
4735
4736         // in formulas:
4737         // IF there is a (s, sa) for which for all (d, da),
4738         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4739         // THEN, for this (s, sa) and all (colormod, d, da):
4740         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
4741         // OBVIOUSLY, this means that
4742         //   s*colormod * src(s*colormod, d, sa, da) = 0
4743         //   dst(s*colormod, d, sa, da)              = 1
4744
4745         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
4746
4747         // main condition to leave dst color invariant:
4748         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4749         //   src == GL_ZERO:
4750         //     s * 0 + d * dst(s, d, sa, da) == d
4751         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4752         //       => colormod is a problem for GL_SRC_COLOR only
4753         //   src == GL_ONE:
4754         //     s + d * dst(s, d, sa, da) == d
4755         //       => s == 0
4756         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4757         //       => colormod is never problematic for these
4758         //   src == GL_SRC_COLOR:
4759         //     s*s + d * dst(s, d, sa, da) == d
4760         //       => s == 0
4761         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4762         //       => colormod is never problematic for these
4763         //   src == GL_ONE_MINUS_SRC_COLOR:
4764         //     s*(1-s) + d * dst(s, d, sa, da) == d
4765         //       => s == 0 or s == 1
4766         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4767         //       => colormod is a problem for GL_SRC_COLOR only
4768         //   src == GL_DST_COLOR
4769         //     s*d + d * dst(s, d, sa, da) == d
4770         //       => s == 1
4771         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4772         //       => colormod is always a problem
4773         //     or
4774         //       => s == 0
4775         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4776         //       => colormod is never problematic for these
4777         //       => BUT, we do not know s! We must assume it is problematic
4778         //       then... except in GL_ONE case, where we know all invariant
4779         //       cases are fine
4780         //   src == GL_ONE_MINUS_DST_COLOR
4781         //     s*(1-d) + d * dst(s, d, sa, da) == d
4782         //       => s == 0 (1-d is impossible to handle for our desired result)
4783         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4784         //       => colormod is never problematic for these
4785         //   src == GL_SRC_ALPHA
4786         //     s*sa + d * dst(s, d, sa, da) == d
4787         //       => s == 0, or sa == 0
4788         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4789         //       => colormod breaks in the case GL_SRC_COLOR only
4790         //   src == GL_ONE_MINUS_SRC_ALPHA
4791         //     s*(1-sa) + d * dst(s, d, sa, da) == d
4792         //       => s == 0, or sa == 1
4793         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4794         //       => colormod breaks in the case GL_SRC_COLOR only
4795         //   src == GL_DST_ALPHA
4796         //     s*da + d * dst(s, d, sa, da) == d
4797         //       => s == 0
4798         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4799         //       => colormod is never problematic for these
4800
4801         switch(src)
4802         {
4803                 case GL_ZERO:
4804                 case GL_ONE_MINUS_SRC_COLOR:
4805                 case GL_SRC_ALPHA:
4806                 case GL_ONE_MINUS_SRC_ALPHA:
4807                         if(dst == GL_SRC_COLOR)
4808                                 return false;
4809                         return true;
4810                 case GL_ONE:
4811                 case GL_SRC_COLOR:
4812                 case GL_ONE_MINUS_DST_COLOR:
4813                 case GL_DST_ALPHA:
4814                 case GL_ONE_MINUS_DST_ALPHA:
4815                         return true;
4816                 case GL_DST_COLOR:
4817                         if(dst == GL_ONE)
4818                                 return true;
4819                         return false;
4820                 default:
4821                         return false;
4822         }
4823 }
4824 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4825 {
4826         // select a permutation of the lighting shader appropriate to this
4827         // combination of texture, entity, light source, and fogging, only use the
4828         // minimum features necessary to avoid wasting rendering time in the
4829         // fragment shader on features that are not being used
4830         unsigned int permutation = 0;
4831         unsigned int mode = 0;
4832         qboolean allow_colormod;
4833         static float dummy_colormod[3] = {1, 1, 1};
4834         float *colormod = rsurface.colormod;
4835         float m16f[16];
4836         if (rsurfacepass == RSURFPASS_BACKGROUND)
4837         {
4838                 // distorted background
4839                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4840                 {
4841                         mode = SHADERMODE_WATER;
4842                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
4843                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
4844                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4845                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4846                 }
4847                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
4848                 {
4849                         mode = SHADERMODE_REFRACTION;
4850                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4851                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4852                 }
4853                 else
4854                 {
4855                         mode = SHADERMODE_GENERIC;
4856                         permutation |= SHADERPERMUTATION_DIFFUSE;
4857                         GL_BlendFunc(GL_ONE, GL_ZERO);
4858                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4859                 }
4860                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4861                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4862                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4863                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4864                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4865                 R_Mesh_ColorPointer(NULL, 0, 0);
4866                 GL_AlphaTest(false);
4867         }
4868         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4869         {
4870                 if (r_glsl_offsetmapping.integer)
4871                 {
4872                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4873                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4874                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4875                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4876                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4877                         {
4878                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4879                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4880                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4881                         }
4882                 }
4883                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4884                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4885                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4886                         permutation |= SHADERPERMUTATION_ALPHAKILL;
4887                 // normalmap (deferred prepass), may use alpha test on diffuse
4888                 mode = SHADERMODE_DEFERREDGEOMETRY;
4889                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4890                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4891                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4892                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4893                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4894                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4895                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4896                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4897                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4898                 else
4899                         R_Mesh_ColorPointer(NULL, 0, 0);
4900                 GL_AlphaTest(false);
4901                 GL_BlendFunc(GL_ONE, GL_ZERO);
4902                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4903         }
4904         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4905         {
4906                 if (r_glsl_offsetmapping.integer)
4907                 {
4908                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4909                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4910                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4911                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4912                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4913                         {
4914                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4915                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4916                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4917                         }
4918                 }
4919                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4920                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4921                 // light source
4922                 mode = SHADERMODE_LIGHTSOURCE;
4923                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4924                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4925                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4926                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4927                 if (diffusescale > 0)
4928                         permutation |= SHADERPERMUTATION_DIFFUSE;
4929                 if (specularscale > 0)
4930                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4931                 if (r_refdef.fogenabled)
4932                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4933                 if (rsurface.texture->colormapping)
4934                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4935                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4936                 {
4937                         if (r_shadow_usingshadowmaprect)
4938                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4939                         if (r_shadow_usingshadowmap2d)
4940                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4941                         if (r_shadow_usingshadowmapcube)
4942                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4943                         else if(r_shadow_shadowmapvsdct)
4944                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4945
4946                         if (r_shadow_shadowmapsampler)
4947                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4948                         if (r_shadow_shadowmappcf > 1)
4949                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4950                         else if (r_shadow_shadowmappcf)
4951                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4952                 }
4953                 if (rsurface.texture->reflectmasktexture)
4954                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4955                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4956                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4957                 {
4958                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4959                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4960                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4961                 }
4962                 else
4963                 {
4964                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4965                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4966                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4967                 }
4968                 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4969                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4970                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4971                 else
4972                         R_Mesh_ColorPointer(NULL, 0, 0);
4973                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4974                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4975                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
4976         }
4977         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4978         {
4979                 if (r_glsl_offsetmapping.integer)
4980                 {
4981                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4982                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4983                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4984                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4985                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4986                         {
4987                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4988                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4989                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4990                         }
4991                 }
4992                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4993                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4994                 // unshaded geometry (fullbright or ambient model lighting)
4995                 mode = SHADERMODE_FLATCOLOR;
4996                 ambientscale = diffusescale = specularscale = 0;
4997                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4998                         permutation |= SHADERPERMUTATION_GLOW;
4999                 if (r_refdef.fogenabled)
5000                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5001                 if (rsurface.texture->colormapping)
5002                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5003                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5004                 {
5005                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5006                         if (r_shadow_usingshadowmaprect)
5007                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5008                         if (r_shadow_usingshadowmap2d)
5009                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5010
5011                         if (r_shadow_shadowmapsampler)
5012                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5013                         if (r_shadow_shadowmappcf > 1)
5014                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5015                         else if (r_shadow_shadowmappcf)
5016                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5017                 }
5018                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5019                         permutation |= SHADERPERMUTATION_REFLECTION;
5020                 if (rsurface.texture->reflectmasktexture)
5021                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5022                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5023                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
5024                 {
5025                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5026                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5027                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5028                 }
5029                 else
5030                 {
5031                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
5032                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
5033                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
5034                 }
5035                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
5036                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
5037                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5038                 else
5039                         R_Mesh_ColorPointer(NULL, 0, 0);
5040                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5041                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5042                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5043         }
5044         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5045         {
5046                 if (r_glsl_offsetmapping.integer)
5047                 {
5048                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5049                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5050                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5051                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5052                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5053                         {
5054                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5055                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5056                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5057                         }
5058                 }
5059                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5060                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5061                 // directional model lighting
5062                 mode = SHADERMODE_LIGHTDIRECTION;
5063                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5064                         permutation |= SHADERPERMUTATION_GLOW;
5065                 permutation |= SHADERPERMUTATION_DIFFUSE;
5066                 if (specularscale > 0)
5067                         permutation |= SHADERPERMUTATION_SPECULAR;
5068                 if (r_refdef.fogenabled)
5069                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5070                 if (rsurface.texture->colormapping)
5071                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5072                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5073                 {
5074                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5075                         if (r_shadow_usingshadowmaprect)
5076                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5077                         if (r_shadow_usingshadowmap2d)
5078                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5079
5080                         if (r_shadow_shadowmapsampler)
5081                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5082                         if (r_shadow_shadowmappcf > 1)
5083                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5084                         else if (r_shadow_shadowmappcf)
5085                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5086                 }
5087                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5088                         permutation |= SHADERPERMUTATION_REFLECTION;
5089                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5090                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5091                 if (rsurface.texture->reflectmasktexture)
5092                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5093                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5094                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
5095                 {
5096                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5097                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5098                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5099                 }
5100                 else
5101                 {
5102                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
5103                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
5104                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
5105                 }
5106                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
5107                 R_Mesh_ColorPointer(NULL, 0, 0);
5108                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5109                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5110                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5111         }
5112         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5113         {
5114                 if (r_glsl_offsetmapping.integer)
5115                 {
5116                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5117                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5118                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5119                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5120                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5121                         {
5122                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5123                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5124                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5125                         }
5126                 }
5127                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5128                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5129                 // ambient model lighting
5130                 mode = SHADERMODE_LIGHTDIRECTION;
5131                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5132                         permutation |= SHADERPERMUTATION_GLOW;
5133                 if (r_refdef.fogenabled)
5134                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5135                 if (rsurface.texture->colormapping)
5136                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5137                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5138                 {
5139                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5140                         if (r_shadow_usingshadowmaprect)
5141                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5142                         if (r_shadow_usingshadowmap2d)
5143                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5144
5145                         if (r_shadow_shadowmapsampler)
5146                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5147                         if (r_shadow_shadowmappcf > 1)
5148                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5149                         else if (r_shadow_shadowmappcf)
5150                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5151                 }
5152                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5153                         permutation |= SHADERPERMUTATION_REFLECTION;
5154                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5155                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5156                 if (rsurface.texture->reflectmasktexture)
5157                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5158                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5159                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
5160                 {
5161                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5162                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5163                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5164                 }
5165                 else
5166                 {
5167                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
5168                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
5169                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
5170                 }
5171                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
5172                 R_Mesh_ColorPointer(NULL, 0, 0);
5173                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5174                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5175                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5176         }
5177         else
5178         {
5179                 if (r_glsl_offsetmapping.integer)
5180                 {
5181                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5182                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5183                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5184                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5185                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5186                         {
5187                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5188                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5189                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5190                         }
5191                 }
5192                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5193                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5194                 // lightmapped wall
5195                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5196                         permutation |= SHADERPERMUTATION_GLOW;
5197                 if (r_refdef.fogenabled)
5198                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5199                 if (rsurface.texture->colormapping)
5200                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5201                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5202                 {
5203                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5204                         if (r_shadow_usingshadowmaprect)
5205                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5206                         if (r_shadow_usingshadowmap2d)
5207                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5208
5209                         if (r_shadow_shadowmapsampler)
5210                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5211                         if (r_shadow_shadowmappcf > 1)
5212                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5213                         else if (r_shadow_shadowmappcf)
5214                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5215                 }
5216                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5217                         permutation |= SHADERPERMUTATION_REFLECTION;
5218                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5219                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5220                 if (rsurface.texture->reflectmasktexture)
5221                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5222                 if (FAKELIGHT_ENABLED)
5223                 {
5224                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5225                         mode = SHADERMODE_FAKELIGHT;
5226                         permutation |= SHADERPERMUTATION_DIFFUSE;
5227                         if (specularscale > 0)
5228                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5229                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
5230                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5231                         else
5232                                 R_Mesh_ColorPointer(NULL, 0, 0);
5233                 }
5234                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5235                 {
5236                         // deluxemapping (light direction texture)
5237                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5238                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5239                         else
5240                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5241                         permutation |= SHADERPERMUTATION_DIFFUSE;
5242                         if (specularscale > 0)
5243                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5244                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5245                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
5246                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5247                         else
5248                                 R_Mesh_ColorPointer(NULL, 0, 0);
5249                 }
5250                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5251                 {
5252                         // fake deluxemapping (uniform light direction in tangentspace)
5253                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5254                         permutation |= SHADERPERMUTATION_DIFFUSE;
5255                         if (specularscale > 0)
5256                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5257                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5258                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
5259                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5260                         else
5261                                 R_Mesh_ColorPointer(NULL, 0, 0);
5262                 }
5263                 else if (rsurface.uselightmaptexture)
5264                 {
5265                         // ordinary lightmapping (q1bsp, q3bsp)
5266                         mode = SHADERMODE_LIGHTMAP;
5267                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5268                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
5269                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5270                         else
5271                                 R_Mesh_ColorPointer(NULL, 0, 0);
5272                 }
5273                 else
5274                 {
5275                         // ordinary vertex coloring (q3bsp)
5276                         mode = SHADERMODE_VERTEXCOLOR;
5277                         R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
5278                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5279                 }
5280                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5281                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
5282                 {
5283                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5284                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5285                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5286                 }
5287                 else
5288                 {
5289                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
5290                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
5291                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
5292                 }
5293                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5294                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5295                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5296         }
5297         if(!allow_colormod)
5298                 colormod = dummy_colormod;
5299         switch(vid.renderpath)
5300         {
5301         case RENDERPATH_GL20:
5302                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5303                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5304                 if (mode == SHADERMODE_LIGHTSOURCE)
5305                 {
5306                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5307                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5308                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5309                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5310                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5311                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5312         
5313                         // additive passes are only darkened by fog, not tinted
5314                         if (r_glsl_permutation->loc_FogColor >= 0)
5315                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5316                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5317                 }
5318                 else
5319                 {
5320                         if (mode == SHADERMODE_FLATCOLOR)
5321                         {
5322                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5323                         }
5324                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5325                         {
5326                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
5327                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5328                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5329                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5330                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5331                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
5332                                 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]);
5333                         }
5334                         else
5335                         {
5336                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5337                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5338                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5339                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5340                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5341                         }
5342                         // additive passes are only darkened by fog, not tinted
5343                         if (r_glsl_permutation->loc_FogColor >= 0)
5344                         {
5345                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5346                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5347                                 else
5348                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5349                         }
5350                         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);
5351                         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]);
5352                         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]);
5353                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5354                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5355                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5356                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5357                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5358                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2fARB(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5359                 }
5360                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5361                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5362                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5363                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5364                 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]);
5365
5366                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5367                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
5368                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5369                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5370                 {
5371                         if (rsurface.texture->pantstexture)
5372                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5373                         else
5374                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5375                 }
5376                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5377                 {
5378                         if (rsurface.texture->shirttexture)
5379                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5380                         else
5381                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5382                 }
5383                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4fARB(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5384                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5385                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5386                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5387                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5388                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2fARB(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5389                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5390
5391         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5392         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5393         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5394                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5395                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5396                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5397                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5398                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5399                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5400                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5401                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5402                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5403                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5404                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5405                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5406                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5407                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5408                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
5409                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , r_texture_blanknormalmap                            );
5410                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5411                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
5412                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
5413                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5414                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5415                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5416                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5417                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5418                 {
5419                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5420                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture                  );
5421                         if (rsurface.rtlight)
5422                         {
5423                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5424                                 if (r_shadow_usingshadowmapcube)
5425                                         if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5426                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5427                         }
5428                 }
5429                 CHECKGLERROR
5430                 break;
5431         case RENDERPATH_CGGL:
5432 #ifdef SUPPORTCG
5433                 R_SetupShader_SetPermutationCG(mode, permutation);
5434                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5435                 if (mode == SHADERMODE_LIGHTSOURCE)
5436                 {
5437                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5438                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5439                 }
5440                 else
5441                 {
5442                         if (mode == SHADERMODE_LIGHTDIRECTION)
5443                         {
5444                                 if (r_cg_permutation->vp_LightDir) cgGLSetParameter3f(r_cg_permutation->vp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
5445                         }
5446                 }
5447                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5448                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5449                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5450                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5451                 if (r_cg_permutation->vp_FogPlane) cgGLSetParameter4f(r_cg_permutation->vp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
5452                 CHECKGLERROR
5453
5454                 if (mode == SHADERMODE_LIGHTSOURCE)
5455                 {
5456                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5457                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5458                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
5459                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
5460                         if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);CHECKCGERROR
5461
5462                         // additive passes are only darkened by fog, not tinted
5463                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5464                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
5465                 }
5466                 else
5467                 {
5468                         if (mode == SHADERMODE_FLATCOLOR)
5469                         {
5470                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
5471                         }
5472                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5473                         {
5474                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);CHECKCGERROR
5475                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);CHECKCGERROR
5476                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
5477                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
5478                                 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
5479                                 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);CHECKCGERROR
5480                                 if (r_cg_permutation->fp_LightDir) cgGLSetParameter3f(r_cg_permutation->fp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
5481                         }
5482                         else
5483                         {
5484                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);CHECKCGERROR
5485                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);CHECKCGERROR
5486                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
5487                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
5488                                 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
5489                         }
5490                         // additive passes are only darkened by fog, not tinted
5491                         if (r_cg_permutation->fp_FogColor)
5492                         {
5493                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5494                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5495                                 else
5496                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5497                                 CHECKCGERROR
5498                         }
5499                         if (r_cg_permutation->fp_DistortScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_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);CHECKCGERROR
5500                         if (r_cg_permutation->fp_ScreenScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);CHECKCGERROR
5501                         if (r_cg_permutation->fp_ScreenCenterRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);CHECKCGERROR
5502                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5503                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5504                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5505                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5506                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
5507                         if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5508                 }
5509                 if (r_cg_permutation->fp_ShadowMap_TextureScale) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
5510                 if (r_cg_permutation->fp_ShadowMap_Parameters) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
5511                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5512                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));CHECKCGERROR
5513                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5514                 if (r_cg_permutation->fp_Color_Pants)
5515                 {
5516                         if (rsurface.texture->pantstexture)
5517                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5518                         else
5519                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5520                         CHECKCGERROR
5521                 }
5522                 if (r_cg_permutation->fp_Color_Shirt)
5523                 {
5524                         if (rsurface.texture->shirttexture)
5525                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5526                         else
5527                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5528                         CHECKCGERROR
5529                 }
5530                 if (r_cg_permutation->fp_FogPlane) cgGLSetParameter4f(r_cg_permutation->fp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
5531                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5532                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5533                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5534                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5535                 if (r_cg_permutation->fp_ScreenToDepth) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
5536                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5537
5538         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
5539         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
5540         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
5541                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
5542                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
5543                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
5544                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
5545                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
5546                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
5547                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
5548                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
5549                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
5550                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
5551                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
5552                 if (r_cg_permutation->fp_Texture_ReflectCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectCube    , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);CHECKCGERROR
5553                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
5554                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
5555                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
5556                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
5557                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5558                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
5559                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
5560                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5561                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5562                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
5563                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
5564                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5565                 {
5566                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5567                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5568                         if (rsurface.rtlight)
5569                         {
5570                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5571                                 if (r_shadow_usingshadowmapcube)
5572                                         if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5573                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5574                         }
5575                 }
5576
5577                 CHECKGLERROR
5578 #endif
5579                 break;
5580         case RENDERPATH_GL13:
5581         case RENDERPATH_GL11:
5582                 break;
5583         }
5584 }
5585
5586 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5587 {
5588         // select a permutation of the lighting shader appropriate to this
5589         // combination of texture, entity, light source, and fogging, only use the
5590         // minimum features necessary to avoid wasting rendering time in the
5591         // fragment shader on features that are not being used
5592         unsigned int permutation = 0;
5593         unsigned int mode = 0;
5594         const float *lightcolorbase = rtlight->currentcolor;
5595         float ambientscale = rtlight->ambientscale;
5596         float diffusescale = rtlight->diffusescale;
5597         float specularscale = rtlight->specularscale;
5598         // this is the location of the light in view space
5599         vec3_t viewlightorigin;
5600         // this transforms from view space (camera) to light space (cubemap)
5601         matrix4x4_t viewtolight;
5602         matrix4x4_t lighttoview;
5603         float viewtolight16f[16];
5604         float range = 1.0f / r_shadow_deferred_8bitrange.value;
5605         // light source
5606         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5607         if (rtlight->currentcubemap != r_texture_whitecube)
5608                 permutation |= SHADERPERMUTATION_CUBEFILTER;
5609         if (diffusescale > 0)
5610                 permutation |= SHADERPERMUTATION_DIFFUSE;
5611         if (specularscale > 0)
5612                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5613         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5614         {
5615                 if (r_shadow_usingshadowmaprect)
5616                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5617                 if (r_shadow_usingshadowmap2d)
5618                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5619                 if (r_shadow_usingshadowmapcube)
5620                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5621                 else if(r_shadow_shadowmapvsdct)
5622                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5623
5624                 if (r_shadow_shadowmapsampler)
5625                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5626                 if (r_shadow_shadowmappcf > 1)
5627                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5628                 else if (r_shadow_shadowmappcf)
5629                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5630         }
5631         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5632         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5633         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5634         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5635         switch(vid.renderpath)
5636         {
5637         case RENDERPATH_GL20:
5638                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5639                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5640                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
5641                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
5642                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
5643                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5644                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2fARB(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5645                 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]);
5646                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1fARB(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5647                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2fARB(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5648                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5649
5650                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5651                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5652                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5653                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5654                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
5655                 if (r_shadow_usingshadowmapcube)
5656                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5657                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5658                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5659                 break;
5660         case RENDERPATH_CGGL:
5661 #ifdef SUPPORTCG
5662                 R_SetupShader_SetPermutationCG(mode, permutation);
5663                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5664                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5665                 if (r_cg_permutation->fp_DeferredColor_Ambient    ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);CHECKCGERROR
5666                 if (r_cg_permutation->fp_DeferredColor_Diffuse    ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);CHECKCGERROR
5667                 if (r_cg_permutation->fp_DeferredColor_Specular   ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);CHECKCGERROR
5668                 if (r_cg_permutation->fp_ShadowMap_TextureScale   ) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
5669                 if (r_cg_permutation->fp_ShadowMap_Parameters     ) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
5670                 if (r_cg_permutation->fp_SpecularPower            ) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
5671                 if (r_cg_permutation->fp_ScreenToDepth            ) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
5672                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5673
5674                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5675                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5676                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5677                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5678                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5679                 if (r_shadow_usingshadowmapcube)
5680                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5681                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5682                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5683 #endif
5684                 break;
5685         case RENDERPATH_GL13:
5686         case RENDERPATH_GL11:
5687                 break;
5688         }
5689 }
5690
5691 #define SKINFRAME_HASH 1024
5692
5693 typedef struct
5694 {
5695         int loadsequence; // incremented each level change
5696         memexpandablearray_t array;
5697         skinframe_t *hash[SKINFRAME_HASH];
5698 }
5699 r_skinframe_t;
5700 r_skinframe_t r_skinframe;
5701
5702 void R_SkinFrame_PrepareForPurge(void)
5703 {
5704         r_skinframe.loadsequence++;
5705         // wrap it without hitting zero
5706         if (r_skinframe.loadsequence >= 200)
5707                 r_skinframe.loadsequence = 1;
5708 }
5709
5710 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5711 {
5712         if (!skinframe)
5713                 return;
5714         // mark the skinframe as used for the purging code
5715         skinframe->loadsequence = r_skinframe.loadsequence;
5716 }
5717
5718 void R_SkinFrame_Purge(void)
5719 {
5720         int i;
5721         skinframe_t *s;
5722         for (i = 0;i < SKINFRAME_HASH;i++)
5723         {
5724                 for (s = r_skinframe.hash[i];s;s = s->next)
5725                 {
5726                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5727                         {
5728                                 if (s->merged == s->base)
5729                                         s->merged = NULL;
5730                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5731                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5732                                 R_PurgeTexture(s->merged);s->merged = NULL;
5733                                 R_PurgeTexture(s->base  );s->base   = NULL;
5734                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5735                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5736                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5737                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5738                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5739                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5740                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
5741                                 s->loadsequence = 0;
5742                         }
5743                 }
5744         }
5745 }
5746
5747 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5748         skinframe_t *item;
5749         char basename[MAX_QPATH];
5750
5751         Image_StripImageExtension(name, basename, sizeof(basename));
5752
5753         if( last == NULL ) {
5754                 int hashindex;
5755                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5756                 item = r_skinframe.hash[hashindex];
5757         } else {
5758                 item = last->next;
5759         }
5760
5761         // linearly search through the hash bucket
5762         for( ; item ; item = item->next ) {
5763                 if( !strcmp( item->basename, basename ) ) {
5764                         return item;
5765                 }
5766         }
5767         return NULL;
5768 }
5769
5770 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5771 {
5772         skinframe_t *item;
5773         int hashindex;
5774         char basename[MAX_QPATH];
5775
5776         Image_StripImageExtension(name, basename, sizeof(basename));
5777
5778         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5779         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5780                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5781                         break;
5782
5783         if (!item) {
5784                 rtexture_t *dyntexture;
5785                 // check whether its a dynamic texture
5786                 dyntexture = CL_GetDynTexture( basename );
5787                 if (!add && !dyntexture)
5788                         return NULL;
5789                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5790                 memset(item, 0, sizeof(*item));
5791                 strlcpy(item->basename, basename, sizeof(item->basename));
5792                 item->base = dyntexture; // either NULL or dyntexture handle
5793                 item->textureflags = textureflags;
5794                 item->comparewidth = comparewidth;
5795                 item->compareheight = compareheight;
5796                 item->comparecrc = comparecrc;
5797                 item->next = r_skinframe.hash[hashindex];
5798                 r_skinframe.hash[hashindex] = item;
5799         }
5800         else if( item->base == NULL )
5801         {
5802                 rtexture_t *dyntexture;
5803                 // check whether its a dynamic texture
5804                 // 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]
5805                 dyntexture = CL_GetDynTexture( basename );
5806                 item->base = dyntexture; // either NULL or dyntexture handle
5807         }
5808
5809         R_SkinFrame_MarkUsed(item);
5810         return item;
5811 }
5812
5813 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5814         { \
5815                 unsigned long long avgcolor[5], wsum; \
5816                 int pix, comp, w; \
5817                 avgcolor[0] = 0; \
5818                 avgcolor[1] = 0; \
5819                 avgcolor[2] = 0; \
5820                 avgcolor[3] = 0; \
5821                 avgcolor[4] = 0; \
5822                 wsum = 0; \
5823                 for(pix = 0; pix < cnt; ++pix) \
5824                 { \
5825                         w = 0; \
5826                         for(comp = 0; comp < 3; ++comp) \
5827                                 w += getpixel; \
5828                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5829                         { \
5830                                 ++wsum; \
5831                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5832                                 w = getpixel; \
5833                                 for(comp = 0; comp < 3; ++comp) \
5834                                         avgcolor[comp] += getpixel * w; \
5835                                 avgcolor[3] += w; \
5836                         } \
5837                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5838                         avgcolor[4] += getpixel; \
5839                 } \
5840                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5841                         avgcolor[3] = 1; \
5842                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5843                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5844                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5845                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5846         }
5847
5848 extern cvar_t gl_picmip;
5849 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5850 {
5851         int j;
5852         unsigned char *pixels;
5853         unsigned char *bumppixels;
5854         unsigned char *basepixels = NULL;
5855         int basepixels_width = 0;
5856         int basepixels_height = 0;
5857         skinframe_t *skinframe;
5858         rtexture_t *ddsbase = NULL;
5859         qboolean ddshasalpha = false;
5860         float ddsavgcolor[4];
5861         char basename[MAX_QPATH];
5862         int miplevel = R_PicmipForFlags(textureflags);
5863         int savemiplevel = miplevel;
5864         int mymiplevel;
5865
5866         if (cls.state == ca_dedicated)
5867                 return NULL;
5868
5869         // return an existing skinframe if already loaded
5870         // if loading of the first image fails, don't make a new skinframe as it
5871         // would cause all future lookups of this to be missing
5872         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5873         if (skinframe && skinframe->base)
5874                 return skinframe;
5875
5876         Image_StripImageExtension(name, basename, sizeof(basename));
5877
5878         // check for DDS texture file first
5879         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
5880         {
5881                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer, &miplevel);
5882                 if (basepixels == NULL)
5883                         return NULL;
5884         }
5885
5886         // FIXME handle miplevel
5887
5888         if (developer_loading.integer)
5889                 Con_Printf("loading skin \"%s\"\n", name);
5890
5891         // we've got some pixels to store, so really allocate this new texture now
5892         if (!skinframe)
5893                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5894         skinframe->stain = NULL;
5895         skinframe->merged = NULL;
5896         skinframe->base = NULL;
5897         skinframe->pants = NULL;
5898         skinframe->shirt = NULL;
5899         skinframe->nmap = NULL;
5900         skinframe->gloss = NULL;
5901         skinframe->glow = NULL;
5902         skinframe->fog = NULL;
5903         skinframe->reflect = NULL;
5904         skinframe->hasalpha = false;
5905
5906         if (ddsbase)
5907         {
5908                 skinframe->base = ddsbase;
5909                 skinframe->hasalpha = ddshasalpha;
5910                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5911                 if (r_loadfog && skinframe->hasalpha)
5912                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
5913                 //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]);
5914         }
5915         else
5916         {
5917                 basepixels_width = image_width;
5918                 basepixels_height = image_height;
5919                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
5920                 if (textureflags & TEXF_ALPHA)
5921                 {
5922                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5923                         {
5924                                 if (basepixels[j] < 255)
5925                                 {
5926                                         skinframe->hasalpha = true;
5927                                         break;
5928                                 }
5929                         }
5930                         if (r_loadfog && skinframe->hasalpha)
5931                         {
5932                                 // has transparent pixels
5933                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5934                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5935                                 {
5936                                         pixels[j+0] = 255;
5937                                         pixels[j+1] = 255;
5938                                         pixels[j+2] = 255;
5939                                         pixels[j+3] = basepixels[j+3];
5940                                 }
5941                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
5942                                 Mem_Free(pixels);
5943                         }
5944                 }
5945                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5946                 //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]);
5947                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5948                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
5949                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5950                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
5951         }
5952
5953         if (r_loaddds)
5954         {
5955                 mymiplevel = savemiplevel;
5956                 if (r_loadnormalmap)
5957                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
5958                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5959                 if (r_loadgloss)
5960                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5961                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5962                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5963                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5964         }
5965
5966         // _norm is the name used by tenebrae and has been adopted as standard
5967         if (r_loadnormalmap && skinframe->nmap == NULL)
5968         {
5969                 mymiplevel = savemiplevel;
5970                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
5971                 {
5972                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
5973                         Mem_Free(pixels);
5974                         pixels = NULL;
5975                 }
5976                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
5977                 {
5978                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5979                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5980                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
5981                         Mem_Free(pixels);
5982                         Mem_Free(bumppixels);
5983                 }
5984                 else if (r_shadow_bumpscale_basetexture.value > 0)
5985                 {
5986                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5987                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5988                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
5989                         Mem_Free(pixels);
5990                 }
5991                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5992                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
5993         }
5994
5995         // _luma is supported only for tenebrae compatibility
5996         // _glow is the preferred name
5997         mymiplevel = savemiplevel;
5998         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel))))
5999         {
6000                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6001                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6002                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6003                 Mem_Free(pixels);pixels = NULL;
6004         }
6005
6006         mymiplevel = savemiplevel;
6007         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))
6008         {
6009                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6010                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6011                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6012                 Mem_Free(pixels);
6013                 pixels = NULL;
6014         }
6015
6016         mymiplevel = savemiplevel;
6017         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))
6018         {
6019                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6020                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6021                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6022                 Mem_Free(pixels);
6023                 pixels = NULL;
6024         }
6025
6026         mymiplevel = savemiplevel;
6027         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))
6028         {
6029                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6030                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6031                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6032                 Mem_Free(pixels);
6033                 pixels = NULL;
6034         }
6035
6036         mymiplevel = savemiplevel;
6037         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))
6038         {
6039                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6040                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6041                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6042                 Mem_Free(pixels);
6043                 pixels = NULL;
6044         }
6045
6046         if (basepixels)
6047                 Mem_Free(basepixels);
6048
6049         return skinframe;
6050 }
6051
6052 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6053 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6054 {
6055         int i;
6056         unsigned char *temp1, *temp2;
6057         skinframe_t *skinframe;
6058
6059         if (cls.state == ca_dedicated)
6060                 return NULL;
6061
6062         // if already loaded just return it, otherwise make a new skinframe
6063         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6064         if (skinframe && skinframe->base)
6065                 return skinframe;
6066
6067         skinframe->stain = NULL;
6068         skinframe->merged = NULL;
6069         skinframe->base = NULL;
6070         skinframe->pants = NULL;
6071         skinframe->shirt = NULL;
6072         skinframe->nmap = NULL;
6073         skinframe->gloss = NULL;
6074         skinframe->glow = NULL;
6075         skinframe->fog = NULL;
6076         skinframe->reflect = NULL;
6077         skinframe->hasalpha = false;
6078
6079         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6080         if (!skindata)
6081                 return NULL;
6082
6083         if (developer_loading.integer)
6084                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6085
6086         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6087         {
6088                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6089                 temp2 = temp1 + width * height * 4;
6090                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6091                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6092                 Mem_Free(temp1);
6093         }
6094         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6095         if (textureflags & TEXF_ALPHA)
6096         {
6097                 for (i = 3;i < width * height * 4;i += 4)
6098                 {
6099                         if (skindata[i] < 255)
6100                         {
6101                                 skinframe->hasalpha = true;
6102                                 break;
6103                         }
6104                 }
6105                 if (r_loadfog && skinframe->hasalpha)
6106                 {
6107                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6108                         memcpy(fogpixels, skindata, width * height * 4);
6109                         for (i = 0;i < width * height * 4;i += 4)
6110                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6111                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6112                         Mem_Free(fogpixels);
6113                 }
6114         }
6115
6116         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6117         //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]);
6118
6119         return skinframe;
6120 }
6121
6122 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6123 {
6124         int i;
6125         int featuresmask;
6126         skinframe_t *skinframe;
6127
6128         if (cls.state == ca_dedicated)
6129                 return NULL;
6130
6131         // if already loaded just return it, otherwise make a new skinframe
6132         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6133         if (skinframe && skinframe->base)
6134                 return skinframe;
6135
6136         skinframe->stain = NULL;
6137         skinframe->merged = NULL;
6138         skinframe->base = NULL;
6139         skinframe->pants = NULL;
6140         skinframe->shirt = NULL;
6141         skinframe->nmap = NULL;
6142         skinframe->gloss = NULL;
6143         skinframe->glow = NULL;
6144         skinframe->fog = NULL;
6145         skinframe->reflect = NULL;
6146         skinframe->hasalpha = false;
6147
6148         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6149         if (!skindata)
6150                 return NULL;
6151
6152         if (developer_loading.integer)
6153                 Con_Printf("loading quake skin \"%s\"\n", name);
6154
6155         // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
6156         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
6157         memcpy(skinframe->qpixels, skindata, width*height);
6158         skinframe->qwidth = width;
6159         skinframe->qheight = height;
6160
6161         featuresmask = 0;
6162         for (i = 0;i < width * height;i++)
6163                 featuresmask |= palette_featureflags[skindata[i]];
6164
6165         skinframe->hasalpha = false;
6166         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6167         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6168         skinframe->qgeneratemerged = true;
6169         skinframe->qgeneratebase = skinframe->qhascolormapping;
6170         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6171
6172         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6173         //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]);
6174
6175         return skinframe;
6176 }
6177
6178 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6179 {
6180         int width;
6181         int height;
6182         unsigned char *skindata;
6183
6184         if (!skinframe->qpixels)
6185                 return;
6186
6187         if (!skinframe->qhascolormapping)
6188                 colormapped = false;
6189
6190         if (colormapped)
6191         {
6192                 if (!skinframe->qgeneratebase)
6193                         return;
6194         }
6195         else
6196         {
6197                 if (!skinframe->qgeneratemerged)
6198                         return;
6199         }
6200
6201         width = skinframe->qwidth;
6202         height = skinframe->qheight;
6203         skindata = skinframe->qpixels;
6204
6205         if (skinframe->qgeneratenmap)
6206         {
6207                 unsigned char *temp1, *temp2;
6208                 skinframe->qgeneratenmap = false;
6209                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6210                 temp2 = temp1 + width * height * 4;
6211                 // use either a custom palette or the quake palette
6212                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6213                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6214                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6215                 Mem_Free(temp1);
6216         }
6217
6218         if (skinframe->qgenerateglow)
6219         {
6220                 skinframe->qgenerateglow = false;
6221                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6222         }
6223
6224         if (colormapped)
6225         {
6226                 skinframe->qgeneratebase = false;
6227                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
6228                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6229                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6230         }
6231         else
6232         {
6233                 skinframe->qgeneratemerged = false;
6234                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
6235         }
6236
6237         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6238         {
6239                 Mem_Free(skinframe->qpixels);
6240                 skinframe->qpixels = NULL;
6241         }
6242 }
6243
6244 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
6245 {
6246         int i;
6247         skinframe_t *skinframe;
6248
6249         if (cls.state == ca_dedicated)
6250                 return NULL;
6251
6252         // if already loaded just return it, otherwise make a new skinframe
6253         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6254         if (skinframe && skinframe->base)
6255                 return skinframe;
6256
6257         skinframe->stain = NULL;
6258         skinframe->merged = NULL;
6259         skinframe->base = NULL;
6260         skinframe->pants = NULL;
6261         skinframe->shirt = NULL;
6262         skinframe->nmap = NULL;
6263         skinframe->gloss = NULL;
6264         skinframe->glow = NULL;
6265         skinframe->fog = NULL;
6266         skinframe->reflect = NULL;
6267         skinframe->hasalpha = false;
6268
6269         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6270         if (!skindata)
6271                 return NULL;
6272
6273         if (developer_loading.integer)
6274                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6275
6276         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6277         if (textureflags & TEXF_ALPHA)
6278         {
6279                 for (i = 0;i < width * height;i++)
6280                 {
6281                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6282                         {
6283                                 skinframe->hasalpha = true;
6284                                 break;
6285                         }
6286                 }
6287                 if (r_loadfog && skinframe->hasalpha)
6288                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6289         }
6290
6291         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6292         //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]);
6293
6294         return skinframe;
6295 }
6296
6297 skinframe_t *R_SkinFrame_LoadMissing(void)
6298 {
6299         skinframe_t *skinframe;
6300
6301         if (cls.state == ca_dedicated)
6302                 return NULL;
6303
6304         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6305         skinframe->stain = NULL;
6306         skinframe->merged = NULL;
6307         skinframe->base = NULL;
6308         skinframe->pants = NULL;
6309         skinframe->shirt = NULL;
6310         skinframe->nmap = NULL;
6311         skinframe->gloss = NULL;
6312         skinframe->glow = NULL;
6313         skinframe->fog = NULL;
6314         skinframe->reflect = NULL;
6315         skinframe->hasalpha = false;
6316
6317         skinframe->avgcolor[0] = rand() / RAND_MAX;
6318         skinframe->avgcolor[1] = rand() / RAND_MAX;
6319         skinframe->avgcolor[2] = rand() / RAND_MAX;
6320         skinframe->avgcolor[3] = 1;
6321
6322         return skinframe;
6323 }
6324
6325 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6326 typedef struct suffixinfo_s
6327 {
6328         char *suffix;
6329         qboolean flipx, flipy, flipdiagonal;
6330 }
6331 suffixinfo_t;
6332 static suffixinfo_t suffix[3][6] =
6333 {
6334         {
6335                 {"px",   false, false, false},
6336                 {"nx",   false, false, false},
6337                 {"py",   false, false, false},
6338                 {"ny",   false, false, false},
6339                 {"pz",   false, false, false},
6340                 {"nz",   false, false, false}
6341         },
6342         {
6343                 {"posx", false, false, false},
6344                 {"negx", false, false, false},
6345                 {"posy", false, false, false},
6346                 {"negy", false, false, false},
6347                 {"posz", false, false, false},
6348                 {"negz", false, false, false}
6349         },
6350         {
6351                 {"rt",    true, false,  true},
6352                 {"lf",   false,  true,  true},
6353                 {"ft",    true,  true, false},
6354                 {"bk",   false, false, false},
6355                 {"up",    true, false,  true},
6356                 {"dn",    true, false,  true}
6357         }
6358 };
6359
6360 static int componentorder[4] = {0, 1, 2, 3};
6361
6362 rtexture_t *R_LoadCubemap(const char *basename)
6363 {
6364         int i, j, cubemapsize;
6365         unsigned char *cubemappixels, *image_buffer;
6366         rtexture_t *cubemaptexture;
6367         char name[256];
6368         // must start 0 so the first loadimagepixels has no requested width/height
6369         cubemapsize = 0;
6370         cubemappixels = NULL;
6371         cubemaptexture = NULL;
6372         // keep trying different suffix groups (posx, px, rt) until one loads
6373         for (j = 0;j < 3 && !cubemappixels;j++)
6374         {
6375                 // load the 6 images in the suffix group
6376                 for (i = 0;i < 6;i++)
6377                 {
6378                         // generate an image name based on the base and and suffix
6379                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6380                         // load it
6381                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer, NULL)))
6382                         {
6383                                 // an image loaded, make sure width and height are equal
6384                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6385                                 {
6386                                         // if this is the first image to load successfully, allocate the cubemap memory
6387                                         if (!cubemappixels && image_width >= 1)
6388                                         {
6389                                                 cubemapsize = image_width;
6390                                                 // note this clears to black, so unavailable sides are black
6391                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6392                                         }
6393                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6394                                         if (cubemappixels)
6395                                                 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
6396                                 }
6397                                 else
6398                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6399                                 // free the image
6400                                 Mem_Free(image_buffer);
6401                         }
6402                 }
6403         }
6404         // if a cubemap loaded, upload it
6405         if (cubemappixels)
6406         {
6407                 if (developer_loading.integer)
6408                         Con_Printf("loading cubemap \"%s\"\n", basename);
6409
6410                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6411                 Mem_Free(cubemappixels);
6412         }
6413         else
6414         {
6415                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6416                 if (developer_loading.integer)
6417                 {
6418                         Con_Printf("(tried tried images ");
6419                         for (j = 0;j < 3;j++)
6420                                 for (i = 0;i < 6;i++)
6421                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6422                         Con_Print(" and was unable to find any of them).\n");
6423                 }
6424         }
6425         return cubemaptexture;
6426 }
6427
6428 rtexture_t *R_GetCubemap(const char *basename)
6429 {
6430         int i;
6431         for (i = 0;i < r_texture_numcubemaps;i++)
6432                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6433                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6434         if (i >= MAX_CUBEMAPS)
6435                 return r_texture_whitecube;
6436         r_texture_numcubemaps++;
6437         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6438         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6439         return r_texture_cubemaps[i].texture;
6440 }
6441
6442 void R_FreeCubemaps(void)
6443 {
6444         int i;
6445         for (i = 0;i < r_texture_numcubemaps;i++)
6446         {
6447                 if (developer_loading.integer)
6448                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6449                 if (r_texture_cubemaps[i].texture)
6450                         R_FreeTexture(r_texture_cubemaps[i].texture);
6451         }
6452         r_texture_numcubemaps = 0;
6453 }
6454
6455 void R_Main_FreeViewCache(void)
6456 {
6457         if (r_refdef.viewcache.entityvisible)
6458                 Mem_Free(r_refdef.viewcache.entityvisible);
6459         if (r_refdef.viewcache.world_pvsbits)
6460                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6461         if (r_refdef.viewcache.world_leafvisible)
6462                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6463         if (r_refdef.viewcache.world_surfacevisible)
6464                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6465         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6466 }
6467
6468 void R_Main_ResizeViewCache(void)
6469 {
6470         int numentities = r_refdef.scene.numentities;
6471         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6472         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6473         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6474         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6475         if (r_refdef.viewcache.maxentities < numentities)
6476         {
6477                 r_refdef.viewcache.maxentities = numentities;
6478                 if (r_refdef.viewcache.entityvisible)
6479                         Mem_Free(r_refdef.viewcache.entityvisible);
6480                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6481         }
6482         if (r_refdef.viewcache.world_numclusters != numclusters)
6483         {
6484                 r_refdef.viewcache.world_numclusters = numclusters;
6485                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6486                 if (r_refdef.viewcache.world_pvsbits)
6487                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6488                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6489         }
6490         if (r_refdef.viewcache.world_numleafs != numleafs)
6491         {
6492                 r_refdef.viewcache.world_numleafs = numleafs;
6493                 if (r_refdef.viewcache.world_leafvisible)
6494                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6495                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6496         }
6497         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6498         {
6499                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6500                 if (r_refdef.viewcache.world_surfacevisible)
6501                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6502                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6503         }
6504 }
6505
6506 extern rtexture_t *loadingscreentexture;
6507 void gl_main_start(void)
6508 {
6509         loadingscreentexture = NULL;
6510         r_texture_blanknormalmap = NULL;
6511         r_texture_white = NULL;
6512         r_texture_grey128 = NULL;
6513         r_texture_black = NULL;
6514         r_texture_whitecube = NULL;
6515         r_texture_normalizationcube = NULL;
6516         r_texture_fogattenuation = NULL;
6517         r_texture_fogheighttexture = NULL;
6518         r_texture_gammaramps = NULL;
6519         r_texture_numcubemaps = 0;
6520
6521         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6522         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6523
6524         switch(vid.renderpath)
6525         {
6526         case RENDERPATH_GL20:
6527         case RENDERPATH_CGGL:
6528                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6529                 Cvar_SetValueQuick(&gl_combine, 1);
6530                 Cvar_SetValueQuick(&r_glsl, 1);
6531                 r_loadnormalmap = true;
6532                 r_loadgloss = true;
6533                 r_loadfog = false;
6534                 break;
6535         case RENDERPATH_GL13:
6536                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6537                 Cvar_SetValueQuick(&gl_combine, 1);
6538                 Cvar_SetValueQuick(&r_glsl, 0);
6539                 r_loadnormalmap = false;
6540                 r_loadgloss = false;
6541                 r_loadfog = true;
6542                 break;
6543         case RENDERPATH_GL11:
6544                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6545                 Cvar_SetValueQuick(&gl_combine, 0);
6546                 Cvar_SetValueQuick(&r_glsl, 0);
6547                 r_loadnormalmap = false;
6548                 r_loadgloss = false;
6549                 r_loadfog = true;
6550                 break;
6551         }
6552
6553         R_AnimCache_Free();
6554         R_FrameData_Reset();
6555
6556         r_numqueries = 0;
6557         r_maxqueries = 0;
6558         memset(r_queries, 0, sizeof(r_queries));
6559
6560         r_qwskincache = NULL;
6561         r_qwskincache_size = 0;
6562
6563         // set up r_skinframe loading system for textures
6564         memset(&r_skinframe, 0, sizeof(r_skinframe));
6565         r_skinframe.loadsequence = 1;
6566         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6567
6568         r_main_texturepool = R_AllocTexturePool();
6569         R_BuildBlankTextures();
6570         R_BuildNoTexture();
6571         if (vid.support.arb_texture_cube_map)
6572         {
6573                 R_BuildWhiteCube();
6574                 R_BuildNormalizationCube();
6575         }
6576         r_texture_fogattenuation = NULL;
6577         r_texture_fogheighttexture = NULL;
6578         r_texture_gammaramps = NULL;
6579         //r_texture_fogintensity = NULL;
6580         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6581         memset(&r_waterstate, 0, sizeof(r_waterstate));
6582         r_glsl_permutation = NULL;
6583         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6584         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6585         glslshaderstring = NULL;
6586 #ifdef SUPPORTCG
6587         r_cg_permutation = NULL;
6588         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6589         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
6590         cgshaderstring = NULL;
6591 #endif
6592         memset(&r_svbsp, 0, sizeof (r_svbsp));
6593
6594         r_refdef.fogmasktable_density = 0;
6595 }
6596
6597 void gl_main_shutdown(void)
6598 {
6599         R_AnimCache_Free();
6600         R_FrameData_Reset();
6601
6602         R_Main_FreeViewCache();
6603
6604         if (r_maxqueries)
6605                 qglDeleteQueriesARB(r_maxqueries, r_queries);
6606
6607         r_numqueries = 0;
6608         r_maxqueries = 0;
6609         memset(r_queries, 0, sizeof(r_queries));
6610
6611         r_qwskincache = NULL;
6612         r_qwskincache_size = 0;
6613
6614         // clear out the r_skinframe state
6615         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6616         memset(&r_skinframe, 0, sizeof(r_skinframe));
6617
6618         if (r_svbsp.nodes)
6619                 Mem_Free(r_svbsp.nodes);
6620         memset(&r_svbsp, 0, sizeof (r_svbsp));
6621         R_FreeTexturePool(&r_main_texturepool);
6622         loadingscreentexture = NULL;
6623         r_texture_blanknormalmap = NULL;
6624         r_texture_white = NULL;
6625         r_texture_grey128 = NULL;
6626         r_texture_black = NULL;
6627         r_texture_whitecube = NULL;
6628         r_texture_normalizationcube = NULL;
6629         r_texture_fogattenuation = NULL;
6630         r_texture_fogheighttexture = NULL;
6631         r_texture_gammaramps = NULL;
6632         r_texture_numcubemaps = 0;
6633         //r_texture_fogintensity = NULL;
6634         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6635         memset(&r_waterstate, 0, sizeof(r_waterstate));
6636         r_glsl_permutation = NULL;
6637         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6638         glslshaderstring = NULL;
6639 #ifdef SUPPORTCG
6640         r_cg_permutation = NULL;
6641         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6642         cgshaderstring = NULL;
6643 #endif
6644         R_GLSL_Restart_f();
6645 }
6646
6647 extern void CL_ParseEntityLump(char *entitystring);
6648 void gl_main_newmap(void)
6649 {
6650         // FIXME: move this code to client
6651         char *entities, entname[MAX_QPATH];
6652         if (r_qwskincache)
6653                 Mem_Free(r_qwskincache);
6654         r_qwskincache = NULL;
6655         r_qwskincache_size = 0;
6656         if (cl.worldmodel)
6657         {
6658                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
6659                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6660                 {
6661                         CL_ParseEntityLump(entities);
6662                         Mem_Free(entities);
6663                         return;
6664                 }
6665                 if (cl.worldmodel->brush.entities)
6666                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
6667         }
6668         R_Main_FreeViewCache();
6669
6670         R_FrameData_Reset();
6671 }
6672
6673 void GL_Main_Init(void)
6674 {
6675         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6676
6677         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6678         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6679         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6680         if (gamemode == GAME_NEHAHRA)
6681         {
6682                 Cvar_RegisterVariable (&gl_fogenable);
6683                 Cvar_RegisterVariable (&gl_fogdensity);
6684                 Cvar_RegisterVariable (&gl_fogred);
6685                 Cvar_RegisterVariable (&gl_foggreen);
6686                 Cvar_RegisterVariable (&gl_fogblue);
6687                 Cvar_RegisterVariable (&gl_fogstart);
6688                 Cvar_RegisterVariable (&gl_fogend);
6689                 Cvar_RegisterVariable (&gl_skyclip);
6690         }
6691         Cvar_RegisterVariable(&r_motionblur);
6692         Cvar_RegisterVariable(&r_motionblur_maxblur);
6693         Cvar_RegisterVariable(&r_motionblur_bmin);
6694         Cvar_RegisterVariable(&r_motionblur_vmin);
6695         Cvar_RegisterVariable(&r_motionblur_vmax);
6696         Cvar_RegisterVariable(&r_motionblur_vcoeff);
6697         Cvar_RegisterVariable(&r_motionblur_randomize);
6698         Cvar_RegisterVariable(&r_damageblur);
6699         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6700         Cvar_RegisterVariable(&r_equalize_entities_minambient);
6701         Cvar_RegisterVariable(&r_equalize_entities_by);
6702         Cvar_RegisterVariable(&r_equalize_entities_to);
6703         Cvar_RegisterVariable(&r_depthfirst);
6704         Cvar_RegisterVariable(&r_useinfinitefarclip);
6705         Cvar_RegisterVariable(&r_farclip_base);
6706         Cvar_RegisterVariable(&r_farclip_world);
6707         Cvar_RegisterVariable(&r_nearclip);
6708         Cvar_RegisterVariable(&r_showbboxes);
6709         Cvar_RegisterVariable(&r_showsurfaces);
6710         Cvar_RegisterVariable(&r_showtris);
6711         Cvar_RegisterVariable(&r_shownormals);
6712         Cvar_RegisterVariable(&r_showlighting);
6713         Cvar_RegisterVariable(&r_showshadowvolumes);
6714         Cvar_RegisterVariable(&r_showcollisionbrushes);
6715         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6716         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6717         Cvar_RegisterVariable(&r_showdisabledepthtest);
6718         Cvar_RegisterVariable(&r_drawportals);
6719         Cvar_RegisterVariable(&r_drawentities);
6720         Cvar_RegisterVariable(&r_draw2d);
6721         Cvar_RegisterVariable(&r_drawworld);
6722         Cvar_RegisterVariable(&r_cullentities_trace);
6723         Cvar_RegisterVariable(&r_cullentities_trace_samples);
6724         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6725         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6726         Cvar_RegisterVariable(&r_cullentities_trace_delay);
6727         Cvar_RegisterVariable(&r_drawviewmodel);
6728         Cvar_RegisterVariable(&r_drawexteriormodel);
6729         Cvar_RegisterVariable(&r_speeds);
6730         Cvar_RegisterVariable(&r_fullbrights);
6731         Cvar_RegisterVariable(&r_wateralpha);
6732         Cvar_RegisterVariable(&r_dynamic);
6733         Cvar_RegisterVariable(&r_fakelight);
6734         Cvar_RegisterVariable(&r_fakelight_intensity);
6735         Cvar_RegisterVariable(&r_fullbright);
6736         Cvar_RegisterVariable(&r_shadows);
6737         Cvar_RegisterVariable(&r_shadows_darken);
6738         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6739         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6740         Cvar_RegisterVariable(&r_shadows_throwdistance);
6741         Cvar_RegisterVariable(&r_shadows_throwdirection);
6742         Cvar_RegisterVariable(&r_shadows_focus);
6743         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6744         Cvar_RegisterVariable(&r_q1bsp_skymasking);
6745         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6746         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6747         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6748         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6749         Cvar_RegisterVariable(&r_fog_exp2);
6750         Cvar_RegisterVariable(&r_drawfog);
6751         Cvar_RegisterVariable(&r_transparentdepthmasking);
6752         Cvar_RegisterVariable(&r_texture_dds_load);
6753         Cvar_RegisterVariable(&r_texture_dds_save);
6754         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6755         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6756         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6757         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6758         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6759         Cvar_RegisterVariable(&r_textureunits);
6760         Cvar_RegisterVariable(&gl_combine);
6761         Cvar_RegisterVariable(&r_glsl);
6762         Cvar_RegisterVariable(&r_glsl_deluxemapping);
6763         Cvar_RegisterVariable(&r_glsl_offsetmapping);
6764         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6765         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6766         Cvar_RegisterVariable(&r_glsl_postprocess);
6767         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6768         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6769         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6770         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6771         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
6772         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
6773         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
6774         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
6775
6776         Cvar_RegisterVariable(&r_water);
6777         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6778         Cvar_RegisterVariable(&r_water_clippingplanebias);
6779         Cvar_RegisterVariable(&r_water_refractdistort);
6780         Cvar_RegisterVariable(&r_water_reflectdistort);
6781         Cvar_RegisterVariable(&r_water_scissormode);
6782         Cvar_RegisterVariable(&r_lerpsprites);
6783         Cvar_RegisterVariable(&r_lerpmodels);
6784         Cvar_RegisterVariable(&r_lerplightstyles);
6785         Cvar_RegisterVariable(&r_waterscroll);
6786         Cvar_RegisterVariable(&r_bloom);
6787         Cvar_RegisterVariable(&r_bloom_colorscale);
6788         Cvar_RegisterVariable(&r_bloom_brighten);
6789         Cvar_RegisterVariable(&r_bloom_blur);
6790         Cvar_RegisterVariable(&r_bloom_resolution);
6791         Cvar_RegisterVariable(&r_bloom_colorexponent);
6792         Cvar_RegisterVariable(&r_bloom_colorsubtract);
6793         Cvar_RegisterVariable(&r_hdr);
6794         Cvar_RegisterVariable(&r_hdr_scenebrightness);
6795         Cvar_RegisterVariable(&r_hdr_glowintensity);
6796         Cvar_RegisterVariable(&r_hdr_range);
6797         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6798         Cvar_RegisterVariable(&developer_texturelogging);
6799         Cvar_RegisterVariable(&gl_lightmaps);
6800         Cvar_RegisterVariable(&r_test);
6801         Cvar_RegisterVariable(&r_batchmode);
6802         Cvar_RegisterVariable(&r_glsl_saturation);
6803         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
6804         Cvar_RegisterVariable(&r_framedatasize);
6805         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6806                 Cvar_SetValue("r_fullbrights", 0);
6807         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
6808
6809         Cvar_RegisterVariable(&r_track_sprites);
6810         Cvar_RegisterVariable(&r_track_sprites_flags);
6811         Cvar_RegisterVariable(&r_track_sprites_scalew);
6812         Cvar_RegisterVariable(&r_track_sprites_scaleh);
6813         Cvar_RegisterVariable(&r_overheadsprites_perspective);
6814         Cvar_RegisterVariable(&r_overheadsprites_pushback);
6815 }
6816
6817 extern void R_Textures_Init(void);
6818 extern void GL_Draw_Init(void);
6819 extern void GL_Main_Init(void);
6820 extern void R_Shadow_Init(void);
6821 extern void R_Sky_Init(void);
6822 extern void GL_Surf_Init(void);
6823 extern void R_Particles_Init(void);
6824 extern void R_Explosion_Init(void);
6825 extern void gl_backend_init(void);
6826 extern void Sbar_Init(void);
6827 extern void R_LightningBeams_Init(void);
6828 extern void Mod_RenderInit(void);
6829 extern void Font_Init(void);
6830
6831 void Render_Init(void)
6832 {
6833         gl_backend_init();
6834         R_Textures_Init();
6835         GL_Main_Init();
6836         Font_Init();
6837         GL_Draw_Init();
6838         R_Shadow_Init();
6839         R_Sky_Init();
6840         GL_Surf_Init();
6841         Sbar_Init();
6842         R_Particles_Init();
6843         R_Explosion_Init();
6844         R_LightningBeams_Init();
6845         Mod_RenderInit();
6846 }
6847
6848 /*
6849 ===============
6850 GL_Init
6851 ===============
6852 */
6853 extern char *ENGINE_EXTENSIONS;
6854 void GL_Init (void)
6855 {
6856         gl_renderer = (const char *)qglGetString(GL_RENDERER);
6857         gl_vendor = (const char *)qglGetString(GL_VENDOR);
6858         gl_version = (const char *)qglGetString(GL_VERSION);
6859         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6860
6861         if (!gl_extensions)
6862                 gl_extensions = "";
6863         if (!gl_platformextensions)
6864                 gl_platformextensions = "";
6865
6866         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6867         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6868         Con_Printf("GL_VERSION: %s\n", gl_version);
6869         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6870         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6871
6872         VID_CheckExtensions();
6873
6874         // LordHavoc: report supported extensions
6875         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6876
6877         // clear to black (loading plaque will be seen over this)
6878         CHECKGLERROR
6879         qglClearColor(0,0,0,1);CHECKGLERROR
6880         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6881 }
6882
6883 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6884 {
6885         int i;
6886         mplane_t *p;
6887         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6888         {
6889                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6890                 if (i == 4)
6891                         continue;
6892                 p = r_refdef.view.frustum + i;
6893                 switch(p->signbits)
6894                 {
6895                 default:
6896                 case 0:
6897                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6898                                 return true;
6899                         break;
6900                 case 1:
6901                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6902                                 return true;
6903                         break;
6904                 case 2:
6905                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6906                                 return true;
6907                         break;
6908                 case 3:
6909                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6910                                 return true;
6911                         break;
6912                 case 4:
6913                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6914                                 return true;
6915                         break;
6916                 case 5:
6917                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6918                                 return true;
6919                         break;
6920                 case 6:
6921                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6922                                 return true;
6923                         break;
6924                 case 7:
6925                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6926                                 return true;
6927                         break;
6928                 }
6929         }
6930         return false;
6931 }
6932
6933 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6934 {
6935         int i;
6936         const mplane_t *p;
6937         for (i = 0;i < numplanes;i++)
6938         {
6939                 p = planes + i;
6940                 switch(p->signbits)
6941                 {
6942                 default:
6943                 case 0:
6944                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6945                                 return true;
6946                         break;
6947                 case 1:
6948                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6949                                 return true;
6950                         break;
6951                 case 2:
6952                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6953                                 return true;
6954                         break;
6955                 case 3:
6956                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6957                                 return true;
6958                         break;
6959                 case 4:
6960                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6961                                 return true;
6962                         break;
6963                 case 5:
6964                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6965                                 return true;
6966                         break;
6967                 case 6:
6968                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6969                                 return true;
6970                         break;
6971                 case 7:
6972                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6973                                 return true;
6974                         break;
6975                 }
6976         }
6977         return false;
6978 }
6979
6980 //==================================================================================
6981
6982 // LordHavoc: this stores temporary data used within the same frame
6983
6984 qboolean r_framedata_failed;
6985 static size_t r_framedata_size;
6986 static size_t r_framedata_current;
6987 static void *r_framedata_base;
6988
6989 void R_FrameData_Reset(void)
6990 {
6991         if (r_framedata_base)
6992                 Mem_Free(r_framedata_base);
6993         r_framedata_base = NULL;
6994         r_framedata_size = 0;
6995         r_framedata_current = 0;
6996         r_framedata_failed = false;
6997 }
6998
6999 void R_FrameData_NewFrame(void)
7000 {
7001         size_t wantedsize;
7002         if (r_framedata_failed)
7003                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7004         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7005         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7006         if (r_framedata_size != wantedsize)
7007         {
7008                 r_framedata_size = wantedsize;
7009                 if (r_framedata_base)
7010                         Mem_Free(r_framedata_base);
7011                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7012         }
7013         r_framedata_current = 0;
7014         r_framedata_failed = false;
7015 }
7016
7017 void *R_FrameData_Alloc(size_t size)
7018 {
7019         void *data;
7020
7021         // align to 16 byte boundary
7022         size = (size + 15) & ~15;
7023         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7024         r_framedata_current += size;
7025
7026         // check overflow
7027         if (r_framedata_current > r_framedata_size)
7028                 r_framedata_failed = true;
7029
7030         // return NULL on everything after a failure
7031         if (r_framedata_failed)
7032                 return NULL;
7033
7034         return data;
7035 }
7036
7037 void *R_FrameData_Store(size_t size, void *data)
7038 {
7039         void *d = R_FrameData_Alloc(size);
7040         if (d)
7041                 memcpy(d, data, size);
7042         return d;
7043 }
7044
7045 //==================================================================================
7046
7047 // LordHavoc: animcache originally written by Echon, rewritten since then
7048
7049 /**
7050  * Animation cache prevents re-generating mesh data for an animated model
7051  * multiple times in one frame for lighting, shadowing, reflections, etc.
7052  */
7053
7054 void R_AnimCache_Free(void)
7055 {
7056 }
7057
7058 void R_AnimCache_ClearCache(void)
7059 {
7060         int i;
7061         entity_render_t *ent;
7062
7063         for (i = 0;i < r_refdef.scene.numentities;i++)
7064         {
7065                 ent = r_refdef.scene.entities[i];
7066                 ent->animcache_vertex3f = NULL;
7067                 ent->animcache_normal3f = NULL;
7068                 ent->animcache_svector3f = NULL;
7069                 ent->animcache_tvector3f = NULL;
7070         }
7071 }
7072
7073 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7074 {
7075         dp_model_t *model = ent->model;
7076         int numvertices;
7077         // see if it's already cached this frame
7078         if (ent->animcache_vertex3f)
7079         {
7080                 // add normals/tangents if needed
7081                 if (wantnormals || wanttangents)
7082                 {
7083                         if (ent->animcache_normal3f)
7084                                 wantnormals = false;
7085                         if (ent->animcache_svector3f)
7086                                 wanttangents = false;
7087                         if (wantnormals || wanttangents)
7088                         {
7089                                 numvertices = model->surfmesh.num_vertices;
7090                                 if (wantnormals)
7091                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
7092                                 if (wanttangents)
7093                                 {
7094                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
7095                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
7096                                 }
7097                                 if (!r_framedata_failed)
7098                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7099                         }
7100                 }
7101         }
7102         else
7103         {
7104                 // see if this ent is worth caching
7105                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7106                         return false;
7107                 // get some memory for this entity and generate mesh data
7108                 numvertices = model->surfmesh.num_vertices;
7109                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
7110                 if (wantnormals)
7111                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
7112                 if (wanttangents)
7113                 {
7114                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
7115                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
7116                 }
7117                 if (!r_framedata_failed)
7118                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7119         }
7120         return !r_framedata_failed;
7121 }
7122
7123 void R_AnimCache_CacheVisibleEntities(void)
7124 {
7125         int i;
7126         qboolean wantnormals = !r_showsurfaces.integer;
7127         qboolean wanttangents = !r_showsurfaces.integer;
7128
7129         switch(vid.renderpath)
7130         {
7131         case RENDERPATH_GL20:
7132         case RENDERPATH_CGGL:
7133                 break;
7134         case RENDERPATH_GL13:
7135         case RENDERPATH_GL11:
7136                 wanttangents = false;
7137                 break;
7138         }
7139
7140         // TODO: thread this
7141         // NOTE: R_PrepareRTLights() also caches entities
7142
7143         for (i = 0;i < r_refdef.scene.numentities;i++)
7144                 if (r_refdef.viewcache.entityvisible[i])
7145                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7146 }
7147
7148 //==================================================================================
7149
7150 static void R_View_UpdateEntityLighting (void)
7151 {
7152         int i;
7153         entity_render_t *ent;
7154         vec3_t tempdiffusenormal, avg;
7155         vec_t f, fa, fd, fdd;
7156         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7157
7158         for (i = 0;i < r_refdef.scene.numentities;i++)
7159         {
7160                 ent = r_refdef.scene.entities[i];
7161
7162                 // skip unseen models
7163                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7164                         continue;
7165
7166                 // skip bsp models
7167                 if (ent->model && ent->model->brush.num_leafs)
7168                 {
7169                         // TODO: use modellight for r_ambient settings on world?
7170                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7171                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7172                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7173                         continue;
7174                 }
7175
7176                 // fetch the lighting from the worldmodel data
7177                 VectorClear(ent->modellight_ambient);
7178                 VectorClear(ent->modellight_diffuse);
7179                 VectorClear(tempdiffusenormal);
7180                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7181                 {
7182                         vec3_t org;
7183                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7184
7185                         // complete lightning for lit sprites
7186                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7187                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7188                         {
7189                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7190                                         org[2] = org[2] + r_overheadsprites_pushback.value;
7191                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, true, true);
7192                         }
7193                         else
7194                                 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7195
7196                         if(ent->flags & RENDER_EQUALIZE)
7197                         {
7198                                 // first fix up ambient lighting...
7199                                 if(r_equalize_entities_minambient.value > 0)
7200                                 {
7201                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7202                                         if(fd > 0)
7203                                         {
7204                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7205                                                 if(fa < r_equalize_entities_minambient.value * fd)
7206                                                 {
7207                                                         // solve:
7208                                                         //   fa'/fd' = minambient
7209                                                         //   fa'+0.25*fd' = fa+0.25*fd
7210                                                         //   ...
7211                                                         //   fa' = fd' * minambient
7212                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7213                                                         //   ...
7214                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7215                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7216                                                         //   ...
7217                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7218                                                         f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
7219                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7220                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7221                                                 }
7222                                         }
7223                                 }
7224
7225                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7226                                 {
7227                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7228                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7229                                         if(f > 0)
7230                                         {
7231                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7232                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7233                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7234                                         }
7235                                 }
7236                         }
7237                 }
7238                 else // highly rare
7239                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7240
7241                 // move the light direction into modelspace coordinates for lighting code
7242                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7243                 if(VectorLength2(ent->modellight_lightdir) == 0)
7244                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7245                 VectorNormalize(ent->modellight_lightdir);
7246         }
7247 }
7248
7249 #define MAX_LINEOFSIGHTTRACES 64
7250
7251 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7252 {
7253         int i;
7254         vec3_t boxmins, boxmaxs;
7255         vec3_t start;
7256         vec3_t end;
7257         dp_model_t *model = r_refdef.scene.worldmodel;
7258
7259         if (!model || !model->brush.TraceLineOfSight)
7260                 return true;
7261
7262         // expand the box a little
7263         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7264         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7265         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7266         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7267         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7268         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7269
7270         // return true if eye is inside enlarged box
7271         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7272                 return true;
7273
7274         // try center
7275         VectorCopy(eye, start);
7276         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7277         if (model->brush.TraceLineOfSight(model, start, end))
7278                 return true;
7279
7280         // try various random positions
7281         for (i = 0;i < numsamples;i++)
7282         {
7283                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7284                 if (model->brush.TraceLineOfSight(model, start, end))
7285                         return true;
7286         }
7287
7288         return false;
7289 }
7290
7291
7292 static void R_View_UpdateEntityVisible (void)
7293 {
7294         int i;
7295         int renderimask;
7296         int samples;
7297         entity_render_t *ent;
7298
7299         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7300                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7301                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
7302                 :                                                          RENDER_EXTERIORMODEL;
7303         if (!r_drawviewmodel.integer)
7304                 renderimask |= RENDER_VIEWMODEL;
7305         if (!r_drawexteriormodel.integer)
7306                 renderimask |= RENDER_EXTERIORMODEL;
7307         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7308         {
7309                 // worldmodel can check visibility
7310                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7311                 for (i = 0;i < r_refdef.scene.numentities;i++)
7312                 {
7313                         ent = r_refdef.scene.entities[i];
7314                         if (!(ent->flags & renderimask))
7315                         if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
7316                         if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
7317                                 r_refdef.viewcache.entityvisible[i] = true;
7318                 }
7319                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7320                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7321                 {
7322                         for (i = 0;i < r_refdef.scene.numentities;i++)
7323                         {
7324                                 ent = r_refdef.scene.entities[i];
7325                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7326                                 {
7327                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7328                                         if (samples < 0)
7329                                                 continue; // temp entities do pvs only
7330                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7331                                                 ent->last_trace_visibility = realtime;
7332                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7333                                                 r_refdef.viewcache.entityvisible[i] = 0;
7334                                 }
7335                         }
7336                 }
7337         }
7338         else
7339         {
7340                 // no worldmodel or it can't check visibility
7341                 for (i = 0;i < r_refdef.scene.numentities;i++)
7342                 {
7343                         ent = r_refdef.scene.entities[i];
7344                         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));
7345                 }
7346         }
7347 }
7348
7349 /// only used if skyrendermasked, and normally returns false
7350 int R_DrawBrushModelsSky (void)
7351 {
7352         int i, sky;
7353         entity_render_t *ent;
7354
7355         sky = false;
7356         for (i = 0;i < r_refdef.scene.numentities;i++)
7357         {
7358                 if (!r_refdef.viewcache.entityvisible[i])
7359                         continue;
7360                 ent = r_refdef.scene.entities[i];
7361                 if (!ent->model || !ent->model->DrawSky)
7362                         continue;
7363                 ent->model->DrawSky(ent);
7364                 sky = true;
7365         }
7366         return sky;
7367 }
7368
7369 static void R_DrawNoModel(entity_render_t *ent);
7370 static void R_DrawModels(void)
7371 {
7372         int i;
7373         entity_render_t *ent;
7374
7375         for (i = 0;i < r_refdef.scene.numentities;i++)
7376         {
7377                 if (!r_refdef.viewcache.entityvisible[i])
7378                         continue;
7379                 ent = r_refdef.scene.entities[i];
7380                 r_refdef.stats.entities++;
7381                 if (ent->model && ent->model->Draw != NULL)
7382                         ent->model->Draw(ent);
7383                 else
7384                         R_DrawNoModel(ent);
7385         }
7386 }
7387
7388 static void R_DrawModelsDepth(void)
7389 {
7390         int i;
7391         entity_render_t *ent;
7392
7393         for (i = 0;i < r_refdef.scene.numentities;i++)
7394         {
7395                 if (!r_refdef.viewcache.entityvisible[i])
7396                         continue;
7397                 ent = r_refdef.scene.entities[i];
7398                 if (ent->model && ent->model->DrawDepth != NULL)
7399                         ent->model->DrawDepth(ent);
7400         }
7401 }
7402
7403 static void R_DrawModelsDebug(void)
7404 {
7405         int i;
7406         entity_render_t *ent;
7407
7408         for (i = 0;i < r_refdef.scene.numentities;i++)
7409         {
7410                 if (!r_refdef.viewcache.entityvisible[i])
7411                         continue;
7412                 ent = r_refdef.scene.entities[i];
7413                 if (ent->model && ent->model->DrawDebug != NULL)
7414                         ent->model->DrawDebug(ent);
7415         }
7416 }
7417
7418 static void R_DrawModelsAddWaterPlanes(void)
7419 {
7420         int i;
7421         entity_render_t *ent;
7422
7423         for (i = 0;i < r_refdef.scene.numentities;i++)
7424         {
7425                 if (!r_refdef.viewcache.entityvisible[i])
7426                         continue;
7427                 ent = r_refdef.scene.entities[i];
7428                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7429                         ent->model->DrawAddWaterPlanes(ent);
7430         }
7431 }
7432
7433 static void R_View_SetFrustum(const int *scissor)
7434 {
7435         int i;
7436         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
7437         vec3_t forward, left, up, origin, v;
7438
7439         if(scissor)
7440         {
7441                 // flipped x coordinates (because x points left here)
7442                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7443                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7444
7445                 // non-flipped y coordinates
7446                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7447                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7448         }
7449
7450         // we can't trust r_refdef.view.forward and friends in reflected scenes
7451         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7452
7453 #if 0
7454         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7455         r_refdef.view.frustum[0].normal[1] = 0 - 0;
7456         r_refdef.view.frustum[0].normal[2] = -1 - 0;
7457         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7458         r_refdef.view.frustum[1].normal[1] = 0 + 0;
7459         r_refdef.view.frustum[1].normal[2] = -1 + 0;
7460         r_refdef.view.frustum[2].normal[0] = 0 - 0;
7461         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7462         r_refdef.view.frustum[2].normal[2] = -1 - 0;
7463         r_refdef.view.frustum[3].normal[0] = 0 + 0;
7464         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7465         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7466 #endif
7467
7468 #if 0
7469         zNear = r_refdef.nearclip;
7470         nudge = 1.0 - 1.0 / (1<<23);
7471         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7472         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7473         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7474         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7475         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7476         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7477         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7478         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7479 #endif
7480
7481
7482
7483 #if 0
7484         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7485         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7486         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7487         r_refdef.view.frustum[0].dist = m[15] - m[12];
7488
7489         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7490         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7491         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7492         r_refdef.view.frustum[1].dist = m[15] + m[12];
7493
7494         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7495         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7496         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7497         r_refdef.view.frustum[2].dist = m[15] - m[13];
7498
7499         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7500         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7501         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7502         r_refdef.view.frustum[3].dist = m[15] + m[13];
7503
7504         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7505         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7506         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7507         r_refdef.view.frustum[4].dist = m[15] - m[14];
7508
7509         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7510         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7511         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7512         r_refdef.view.frustum[5].dist = m[15] + m[14];
7513 #endif
7514
7515         if (r_refdef.view.useperspective)
7516         {
7517                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7518                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
7519                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
7520                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
7521                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
7522
7523                 // then the normals from the corners relative to origin
7524                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
7525                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
7526                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
7527                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
7528
7529                 // in a NORMAL view, forward cross left == up
7530                 // in a REFLECTED view, forward cross left == down
7531                 // so our cross products above need to be adjusted for a left handed coordinate system
7532                 CrossProduct(forward, left, v);
7533                 if(DotProduct(v, up) < 0)
7534                 {
7535                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
7536                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
7537                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
7538                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
7539                 }
7540
7541                 // Leaving those out was a mistake, those were in the old code, and they
7542                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7543                 // I couldn't reproduce it after adding those normalizations. --blub
7544                 VectorNormalize(r_refdef.view.frustum[0].normal);
7545                 VectorNormalize(r_refdef.view.frustum[1].normal);
7546                 VectorNormalize(r_refdef.view.frustum[2].normal);
7547                 VectorNormalize(r_refdef.view.frustum[3].normal);
7548
7549                 // make the corners absolute
7550                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
7551                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
7552                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
7553                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
7554
7555                 // one more normal
7556                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7557
7558                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7559                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7560                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7561                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7562                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7563         }
7564         else
7565         {
7566                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7567                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7568                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7569                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7570                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7571                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7572                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7573                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7574                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7575                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7576         }
7577         r_refdef.view.numfrustumplanes = 5;
7578
7579         if (r_refdef.view.useclipplane)
7580         {
7581                 r_refdef.view.numfrustumplanes = 6;
7582                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7583         }
7584
7585         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7586                 PlaneClassify(r_refdef.view.frustum + i);
7587
7588         // LordHavoc: note to all quake engine coders, Quake had a special case
7589         // for 90 degrees which assumed a square view (wrong), so I removed it,
7590         // Quake2 has it disabled as well.
7591
7592         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7593         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7594         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7595         //PlaneClassify(&frustum[0]);
7596
7597         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7598         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7599         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7600         //PlaneClassify(&frustum[1]);
7601
7602         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7603         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7604         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7605         //PlaneClassify(&frustum[2]);
7606
7607         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7608         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7609         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7610         //PlaneClassify(&frustum[3]);
7611
7612         // nearclip plane
7613         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7614         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7615         //PlaneClassify(&frustum[4]);
7616 }
7617
7618 void R_View_UpdateWithScissor(const int *myscissor)
7619 {
7620         R_Main_ResizeViewCache();
7621         R_View_SetFrustum(myscissor);
7622         R_View_WorldVisibility(r_refdef.view.useclipplane);
7623         R_View_UpdateEntityVisible();
7624         R_View_UpdateEntityLighting();
7625 }
7626
7627 void R_View_Update(void)
7628 {
7629         R_Main_ResizeViewCache();
7630         R_View_SetFrustum(NULL);
7631         R_View_WorldVisibility(r_refdef.view.useclipplane);
7632         R_View_UpdateEntityVisible();
7633         R_View_UpdateEntityLighting();
7634 }
7635
7636 void R_SetupView(qboolean allowwaterclippingplane)
7637 {
7638         const float *customclipplane = NULL;
7639         float plane[4];
7640         if (r_refdef.view.useclipplane && allowwaterclippingplane)
7641         {
7642                 // LordHavoc: couldn't figure out how to make this approach the
7643                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7644                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7645                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7646                         dist = r_refdef.view.clipplane.dist;
7647                 plane[0] = r_refdef.view.clipplane.normal[0];
7648                 plane[1] = r_refdef.view.clipplane.normal[1];
7649                 plane[2] = r_refdef.view.clipplane.normal[2];
7650                 plane[3] = dist;
7651                 customclipplane = plane;
7652         }
7653
7654         if (!r_refdef.view.useperspective)
7655                 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);
7656         else if (vid.stencil && r_useinfinitefarclip.integer)
7657                 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);
7658         else
7659                 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);
7660         R_SetViewport(&r_refdef.view.viewport);
7661 }
7662
7663 void R_EntityMatrix(const matrix4x4_t *matrix)
7664 {
7665         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7666         {
7667                 gl_modelmatrixchanged = false;
7668                 gl_modelmatrix = *matrix;
7669                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7670                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7671                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7672                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7673                 CHECKGLERROR
7674                 switch(vid.renderpath)
7675                 {
7676                 case RENDERPATH_GL20:
7677                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7678                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7679                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7680                         break;
7681                 case RENDERPATH_CGGL:
7682 #ifdef SUPPORTCG
7683                         CHECKCGERROR
7684                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
7685                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
7686                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7687 #endif
7688                         break;
7689                 case RENDERPATH_GL13:
7690                 case RENDERPATH_GL11:
7691                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7692                         break;
7693                 }
7694         }
7695 }
7696
7697 void R_ResetViewRendering2D(void)
7698 {
7699         r_viewport_t viewport;
7700         DrawQ_Finish();
7701
7702         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7703         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);
7704         R_SetViewport(&viewport);
7705         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7706         GL_Color(1, 1, 1, 1);
7707         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7708         GL_BlendFunc(GL_ONE, GL_ZERO);
7709         GL_AlphaTest(false);
7710         GL_ScissorTest(false);
7711         GL_DepthMask(false);
7712         GL_DepthRange(0, 1);
7713         GL_DepthTest(false);
7714         R_EntityMatrix(&identitymatrix);
7715         R_Mesh_ResetTextureState();
7716         GL_PolygonOffset(0, 0);
7717         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7718         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7719         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7720         qglStencilMask(~0);CHECKGLERROR
7721         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7722         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7723         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
7724 }
7725
7726 void R_ResetViewRendering3D(void)
7727 {
7728         DrawQ_Finish();
7729
7730         R_SetupView(true);
7731         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7732         GL_Color(1, 1, 1, 1);
7733         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7734         GL_BlendFunc(GL_ONE, GL_ZERO);
7735         GL_AlphaTest(false);
7736         GL_ScissorTest(true);
7737         GL_DepthMask(true);
7738         GL_DepthRange(0, 1);
7739         GL_DepthTest(true);
7740         R_EntityMatrix(&identitymatrix);
7741         R_Mesh_ResetTextureState();
7742         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7743         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7744         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7745         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7746         qglStencilMask(~0);CHECKGLERROR
7747         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7748         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7749         GL_CullFace(r_refdef.view.cullface_back);
7750 }
7751
7752 /*
7753 ================
7754 R_RenderView_UpdateViewVectors
7755 ================
7756 */
7757 static void R_RenderView_UpdateViewVectors(void)
7758 {
7759         // break apart the view matrix into vectors for various purposes
7760         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7761         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7762         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7763         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7764         // make an inverted copy of the view matrix for tracking sprites
7765         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7766 }
7767
7768 void R_RenderScene(void);
7769 void R_RenderWaterPlanes(void);
7770
7771 static void R_Water_StartFrame(void)
7772 {
7773         int i;
7774         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
7775         r_waterstate_waterplane_t *p;
7776
7777         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7778                 return;
7779
7780         switch(vid.renderpath)
7781         {
7782         case RENDERPATH_GL20:
7783         case RENDERPATH_CGGL:
7784                 break;
7785         case RENDERPATH_GL13:
7786         case RENDERPATH_GL11:
7787                 return;
7788         }
7789
7790         // set waterwidth and waterheight to the water resolution that will be
7791         // used (often less than the screen resolution for faster rendering)
7792         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7793         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7794
7795         // calculate desired texture sizes
7796         // can't use water if the card does not support the texture size
7797         if (!r_water.integer || r_showsurfaces.integer)
7798                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
7799         else if (vid.support.arb_texture_non_power_of_two)
7800         {
7801                 texturewidth = waterwidth;
7802                 textureheight = waterheight;
7803                 camerawidth = waterwidth;
7804                 cameraheight = waterheight;
7805         }
7806         else
7807         {
7808                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
7809                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
7810                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
7811                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
7812         }
7813
7814         // allocate textures as needed
7815         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
7816         {
7817                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7818                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
7819                 {
7820                         if (p->texture_refraction)
7821                                 R_FreeTexture(p->texture_refraction);
7822                         p->texture_refraction = NULL;
7823                         if (p->texture_reflection)
7824                                 R_FreeTexture(p->texture_reflection);
7825                         p->texture_reflection = NULL;
7826                         if (p->texture_camera)
7827                                 R_FreeTexture(p->texture_camera);
7828                         p->texture_camera = NULL;
7829                 }
7830                 memset(&r_waterstate, 0, sizeof(r_waterstate));
7831                 r_waterstate.texturewidth = texturewidth;
7832                 r_waterstate.textureheight = textureheight;
7833                 r_waterstate.camerawidth = camerawidth;
7834                 r_waterstate.cameraheight = cameraheight;
7835         }
7836
7837         if (r_waterstate.texturewidth)
7838         {
7839                 r_waterstate.enabled = true;
7840
7841                 // when doing a reduced render (HDR) we want to use a smaller area
7842                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
7843                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
7844
7845                 // set up variables that will be used in shader setup
7846                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7847                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7848                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7849                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7850         }
7851
7852         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7853         r_waterstate.numwaterplanes = 0;
7854 }
7855
7856 void R_Water_AddWaterPlane(msurface_t *surface)
7857 {
7858         int triangleindex, planeindex;
7859         const int *e;
7860         vec3_t vert[3];
7861         vec3_t normal;
7862         vec3_t center;
7863         mplane_t plane;
7864         int cam_ent;
7865         r_waterstate_waterplane_t *p;
7866         texture_t *t = R_GetCurrentTexture(surface->texture);
7867         cam_ent = t->camera_entity;
7868         if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
7869                 cam_ent = 0;
7870
7871         // just use the first triangle with a valid normal for any decisions
7872         VectorClear(normal);
7873         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7874         {
7875                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
7876                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
7877                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
7878                 TriangleNormal(vert[0], vert[1], vert[2], normal);
7879                 if (VectorLength2(normal) >= 0.001)
7880                         break;
7881         }
7882
7883         VectorCopy(normal, plane.normal);
7884         VectorNormalize(plane.normal);
7885         plane.dist = DotProduct(vert[0], plane.normal);
7886         PlaneClassify(&plane);
7887         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
7888         {
7889                 // skip backfaces (except if nocullface is set)
7890                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7891                         return;
7892                 VectorNegate(plane.normal, plane.normal);
7893                 plane.dist *= -1;
7894                 PlaneClassify(&plane);
7895         }
7896
7897
7898         // find a matching plane if there is one
7899         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7900                 if(p->camera_entity == t->camera_entity)
7901                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7902                                 break;
7903         if (planeindex >= r_waterstate.maxwaterplanes)
7904                 return; // nothing we can do, out of planes
7905
7906         // if this triangle does not fit any known plane rendered this frame, add one
7907         if (planeindex >= r_waterstate.numwaterplanes)
7908         {
7909                 // store the new plane
7910                 r_waterstate.numwaterplanes++;
7911                 p->plane = plane;
7912                 // clear materialflags and pvs
7913                 p->materialflags = 0;
7914                 p->pvsvalid = false;
7915                 p->camera_entity = t->camera_entity;
7916                 VectorCopy(surface->mins, p->mins);
7917                 VectorCopy(surface->maxs, p->maxs);
7918         }
7919         else
7920         {
7921                 // merge mins/maxs
7922                 p->mins[0] = min(p->mins[0], surface->mins[0]);
7923                 p->mins[1] = min(p->mins[1], surface->mins[1]);
7924                 p->mins[2] = min(p->mins[2], surface->mins[2]);
7925                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
7926                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
7927                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
7928         }
7929         // merge this surface's materialflags into the waterplane
7930         p->materialflags |= t->currentmaterialflags;
7931         if(!(p->materialflags & MATERIALFLAG_CAMERA))
7932         {
7933                 // merge this surface's PVS into the waterplane
7934                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7935                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7936                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7937                 {
7938                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7939                         p->pvsvalid = true;
7940                 }
7941         }
7942 }
7943
7944 static void R_Water_ProcessPlanes(void)
7945 {
7946         int myscissor[4];
7947         r_refdef_view_t originalview;
7948         r_refdef_view_t myview;
7949         int planeindex;
7950         r_waterstate_waterplane_t *p;
7951         vec3_t visorigin;
7952
7953         originalview = r_refdef.view;
7954
7955         // make sure enough textures are allocated
7956         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7957         {
7958                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7959                 {
7960                         if (!p->texture_refraction)
7961                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7962                         if (!p->texture_refraction)
7963                                 goto error;
7964                 }
7965                 else if (p->materialflags & MATERIALFLAG_CAMERA)
7966                 {
7967                         if (!p->texture_camera)
7968                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR, -1, NULL);
7969                         if (!p->texture_camera)
7970                                 goto error;
7971                 }
7972
7973                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7974                 {
7975                         if (!p->texture_reflection)
7976                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7977                         if (!p->texture_reflection)
7978                                 goto error;
7979                 }
7980         }
7981
7982         // render views
7983         r_refdef.view = originalview;
7984         r_refdef.view.showdebug = false;
7985         r_refdef.view.width = r_waterstate.waterwidth;
7986         r_refdef.view.height = r_waterstate.waterheight;
7987         r_refdef.view.useclipplane = true;
7988         myview = r_refdef.view;
7989         r_waterstate.renderingscene = true;
7990         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7991         {
7992                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7993                 {
7994                         r_refdef.view = myview;
7995                         if(r_water_scissormode.integer)
7996                         {
7997                                 R_SetupView(true);
7998                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
7999                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8000                         }
8001
8002                         // render reflected scene and copy into texture
8003                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8004                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8005                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8006                         r_refdef.view.clipplane = p->plane;
8007
8008                         // reverse the cullface settings for this render
8009                         r_refdef.view.cullface_front = GL_FRONT;
8010                         r_refdef.view.cullface_back = GL_BACK;
8011                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8012                         {
8013                                 r_refdef.view.usecustompvs = true;
8014                                 if (p->pvsvalid)
8015                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8016                                 else
8017                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8018                         }
8019
8020                         R_ResetViewRendering3D();
8021                         R_ClearScreen(r_refdef.fogenabled);
8022                         if(r_water_scissormode.integer & 2)
8023                                 R_View_UpdateWithScissor(myscissor);
8024                         else
8025                                 R_View_Update();
8026                         if(r_water_scissormode.integer & 1)
8027                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8028                         R_RenderScene();
8029
8030                         R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8031                 }
8032
8033                 // render the normal view scene and copy into texture
8034                 // (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)
8035                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8036                 {
8037                         r_refdef.view = myview;
8038                         if(r_water_scissormode.integer)
8039                         {
8040                                 R_SetupView(true);
8041                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8042                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8043                         }
8044
8045                         r_waterstate.renderingrefraction = true;
8046
8047                         r_refdef.view.clipplane = p->plane;
8048                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8049                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8050
8051                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8052                         {
8053                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8054                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8055                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8056                                 R_RenderView_UpdateViewVectors();
8057                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8058                                 {
8059                                         r_refdef.view.usecustompvs = true;
8060                                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
8061                                 }
8062                         }
8063
8064                         PlaneClassify(&r_refdef.view.clipplane);
8065
8066                         R_ResetViewRendering3D();
8067                         R_ClearScreen(r_refdef.fogenabled);
8068                         if(r_water_scissormode.integer & 2)
8069                                 R_View_UpdateWithScissor(myscissor);
8070                         else
8071                                 R_View_Update();
8072                         if(r_water_scissormode.integer & 1)
8073                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8074                         R_RenderScene();
8075
8076                         R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8077                         r_waterstate.renderingrefraction = false;
8078                 }
8079                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8080                 {
8081                         r_refdef.view = myview;
8082
8083                         r_refdef.view.clipplane = p->plane;
8084                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8085                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8086
8087                         r_refdef.view.width = r_waterstate.camerawidth;
8088                         r_refdef.view.height = r_waterstate.cameraheight;
8089                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8090                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8091
8092                         if(p->camera_entity)
8093                         {
8094                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8095                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8096                         }
8097
8098                         // note: all of the view is used for displaying... so
8099                         // there is no use in scissoring
8100
8101                         // reverse the cullface settings for this render
8102                         r_refdef.view.cullface_front = GL_FRONT;
8103                         r_refdef.view.cullface_back = GL_BACK;
8104                         // also reverse the view matrix
8105                         Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, 1, -1); // this serves to invert texcoords in the result, as the copied texture is mapped the wrong way round
8106                         R_RenderView_UpdateViewVectors();
8107                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8108                         {
8109                                 r_refdef.view.usecustompvs = true;
8110                                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
8111                         }
8112                         
8113                         // camera needs no clipplane
8114                         r_refdef.view.useclipplane = false;
8115
8116                         PlaneClassify(&r_refdef.view.clipplane);
8117
8118                         R_ResetViewRendering3D();
8119                         R_ClearScreen(r_refdef.fogenabled);
8120                         R_View_Update();
8121                         R_RenderScene();
8122
8123                         R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8124                         r_waterstate.renderingrefraction = false;
8125                 }
8126
8127         }
8128         r_waterstate.renderingscene = false;
8129         r_refdef.view = originalview;
8130         R_ResetViewRendering3D();
8131         R_ClearScreen(r_refdef.fogenabled);
8132         R_View_Update();
8133         return;
8134 error:
8135         r_refdef.view = originalview;
8136         r_waterstate.renderingscene = false;
8137         Cvar_SetValueQuick(&r_water, 0);
8138         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8139         return;
8140 }
8141
8142 void R_Bloom_StartFrame(void)
8143 {
8144         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8145
8146         switch(vid.renderpath)
8147         {
8148         case RENDERPATH_GL20:
8149         case RENDERPATH_CGGL:
8150                 break;
8151         case RENDERPATH_GL13:
8152         case RENDERPATH_GL11:
8153                 return;
8154         }
8155
8156         // set bloomwidth and bloomheight to the bloom resolution that will be
8157         // used (often less than the screen resolution for faster rendering)
8158         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8159         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8160         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8161         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8162         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8163
8164         // calculate desired texture sizes
8165         if (vid.support.arb_texture_non_power_of_two)
8166         {
8167                 screentexturewidth = r_refdef.view.width;
8168                 screentextureheight = r_refdef.view.height;
8169                 bloomtexturewidth = r_bloomstate.bloomwidth;
8170                 bloomtextureheight = r_bloomstate.bloomheight;
8171         }
8172         else
8173         {
8174                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8175                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8176                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8177                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8178         }
8179
8180         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 > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
8181         {
8182                 Cvar_SetValueQuick(&r_hdr, 0);
8183                 Cvar_SetValueQuick(&r_bloom, 0);
8184                 Cvar_SetValueQuick(&r_motionblur, 0);
8185                 Cvar_SetValueQuick(&r_damageblur, 0);
8186         }
8187
8188         if (!(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)))
8189                 screentexturewidth = screentextureheight = 0;
8190         if (!r_hdr.integer && !r_bloom.integer)
8191                 bloomtexturewidth = bloomtextureheight = 0;
8192
8193         // allocate textures as needed
8194         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8195         {
8196                 if (r_bloomstate.texture_screen)
8197                         R_FreeTexture(r_bloomstate.texture_screen);
8198                 r_bloomstate.texture_screen = NULL;
8199                 r_bloomstate.screentexturewidth = screentexturewidth;
8200                 r_bloomstate.screentextureheight = screentextureheight;
8201                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8202                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
8203         }
8204         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8205         {
8206                 if (r_bloomstate.texture_bloom)
8207                         R_FreeTexture(r_bloomstate.texture_bloom);
8208                 r_bloomstate.texture_bloom = NULL;
8209                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8210                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8211                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8212                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8213         }
8214
8215         // when doing a reduced render (HDR) we want to use a smaller area
8216         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8217         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8218         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8219         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8220         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8221
8222         // set up a texcoord array for the full resolution screen image
8223         // (we have to keep this around to copy back during final render)
8224         r_bloomstate.screentexcoord2f[0] = 0;
8225         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8226         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8227         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8228         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8229         r_bloomstate.screentexcoord2f[5] = 0;
8230         r_bloomstate.screentexcoord2f[6] = 0;
8231         r_bloomstate.screentexcoord2f[7] = 0;
8232
8233         // set up a texcoord array for the reduced resolution bloom image
8234         // (which will be additive blended over the screen image)
8235         r_bloomstate.bloomtexcoord2f[0] = 0;
8236         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8237         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8238         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8239         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8240         r_bloomstate.bloomtexcoord2f[5] = 0;
8241         r_bloomstate.bloomtexcoord2f[6] = 0;
8242         r_bloomstate.bloomtexcoord2f[7] = 0;
8243
8244         if (r_hdr.integer || r_bloom.integer)
8245         {
8246                 r_bloomstate.enabled = true;
8247                 r_bloomstate.hdr = r_hdr.integer != 0;
8248         }
8249
8250         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);
8251 }
8252
8253 void R_Bloom_CopyBloomTexture(float colorscale)
8254 {
8255         r_refdef.stats.bloom++;
8256
8257         // scale down screen texture to the bloom texture size
8258         CHECKGLERROR
8259         R_SetViewport(&r_bloomstate.viewport);
8260         GL_BlendFunc(GL_ONE, GL_ZERO);
8261         GL_Color(colorscale, colorscale, colorscale, 1);
8262         // TODO: optimize with multitexture or GLSL
8263         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
8264         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8265         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8266         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8267
8268         // we now have a bloom image in the framebuffer
8269         // copy it into the bloom image texture for later processing
8270         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
8271         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8272 }
8273
8274 void R_Bloom_CopyHDRTexture(void)
8275 {
8276         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8277         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8278 }
8279
8280 void R_Bloom_MakeTexture(void)
8281 {
8282         int x, range, dir;
8283         float xoffset, yoffset, r, brighten;
8284
8285         r_refdef.stats.bloom++;
8286
8287         R_ResetViewRendering2D();
8288         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8289         R_Mesh_ColorPointer(NULL, 0, 0);
8290
8291         // we have a bloom image in the framebuffer
8292         CHECKGLERROR
8293         R_SetViewport(&r_bloomstate.viewport);
8294
8295         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8296         {
8297                 x *= 2;
8298                 r = bound(0, r_bloom_colorexponent.value / x, 1);
8299                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8300                 GL_Color(r, r, r, 1);
8301                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8302                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
8303                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8304                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8305
8306                 // copy the vertically blurred bloom view to a texture
8307                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
8308                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8309         }
8310
8311         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8312         brighten = r_bloom_brighten.value;
8313         if (r_hdr.integer)
8314                 brighten *= r_hdr_range.value;
8315         brighten = sqrt(brighten);
8316         if(range >= 1)
8317                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8318         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8319         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
8320
8321         for (dir = 0;dir < 2;dir++)
8322         {
8323                 // blend on at multiple vertical offsets to achieve a vertical blur
8324                 // TODO: do offset blends using GLSL
8325                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8326                 GL_BlendFunc(GL_ONE, GL_ZERO);
8327                 for (x = -range;x <= range;x++)
8328                 {
8329                         if (!dir){xoffset = 0;yoffset = x;}
8330                         else {xoffset = x;yoffset = 0;}
8331                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
8332                         yoffset /= (float)r_bloomstate.bloomtextureheight;
8333                         // compute a texcoord array with the specified x and y offset
8334                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8335                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8336                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8337                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8338                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8339                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8340                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8341                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8342                         // this r value looks like a 'dot' particle, fading sharply to
8343                         // black at the edges
8344                         // (probably not realistic but looks good enough)
8345                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8346                         //r = brighten/(range*2+1);
8347                         r = brighten / (range * 2 + 1);
8348                         if(range >= 1)
8349                                 r *= (1 - x*x/(float)(range*range));
8350                         GL_Color(r, r, r, 1);
8351                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8352                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8353                         GL_BlendFunc(GL_ONE, GL_ONE);
8354                 }
8355
8356                 // copy the vertically blurred bloom view to a texture
8357                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
8358                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8359         }
8360
8361         // apply subtract last
8362         // (just like it would be in a GLSL shader)
8363         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
8364         {
8365                 GL_BlendFunc(GL_ONE, GL_ZERO);
8366                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8367                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
8368                 GL_Color(1, 1, 1, 1);
8369                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8370                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8371
8372                 GL_BlendFunc(GL_ONE, GL_ONE);
8373                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
8374                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8375                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
8376                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
8377                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8378                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8379                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
8380
8381                 // copy the darkened bloom view to a texture
8382                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
8383                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8384         }
8385 }
8386
8387 void R_HDR_RenderBloomTexture(void)
8388 {
8389         int oldwidth, oldheight;
8390         float oldcolorscale;
8391
8392         oldcolorscale = r_refdef.view.colorscale;
8393         oldwidth = r_refdef.view.width;
8394         oldheight = r_refdef.view.height;
8395         r_refdef.view.width = r_bloomstate.bloomwidth;
8396         r_refdef.view.height = r_bloomstate.bloomheight;
8397
8398         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
8399         // TODO: add exposure compensation features
8400         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8401
8402         r_refdef.view.showdebug = false;
8403         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8404
8405         R_ResetViewRendering3D();
8406
8407         R_ClearScreen(r_refdef.fogenabled);
8408         if (r_timereport_active)
8409                 R_TimeReport("HDRclear");
8410
8411         R_View_Update();
8412         if (r_timereport_active)
8413                 R_TimeReport("visibility");
8414
8415         // only do secondary renders with HDR if r_hdr is 2 or higher
8416         r_waterstate.numwaterplanes = 0;
8417         if (r_waterstate.enabled && r_hdr.integer >= 2)
8418                 R_RenderWaterPlanes();
8419
8420         r_refdef.view.showdebug = true;
8421         R_RenderScene();
8422         r_waterstate.numwaterplanes = 0;
8423
8424         R_ResetViewRendering2D();
8425
8426         R_Bloom_CopyHDRTexture();
8427         R_Bloom_MakeTexture();
8428
8429         // restore the view settings
8430         r_refdef.view.width = oldwidth;
8431         r_refdef.view.height = oldheight;
8432         r_refdef.view.colorscale = oldcolorscale;
8433
8434         R_ResetViewRendering3D();
8435
8436         R_ClearScreen(r_refdef.fogenabled);
8437         if (r_timereport_active)
8438                 R_TimeReport("viewclear");
8439 }
8440
8441 static void R_BlendView(void)
8442 {
8443         unsigned int permutation;
8444         float uservecs[4][4];
8445
8446         switch (vid.renderpath)
8447         {
8448         case RENDERPATH_GL20:
8449         case RENDERPATH_CGGL:
8450                 permutation =
8451                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8452                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8453                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8454                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8455                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8456
8457                 if (r_bloomstate.texture_screen)
8458                 {
8459                         // make sure the buffer is available
8460                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8461
8462                         R_ResetViewRendering2D();
8463                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8464                         R_Mesh_ColorPointer(NULL, 0, 0);
8465
8466                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8467                         {
8468                                 // declare variables
8469                                 float speed;
8470                                 static float avgspeed;
8471
8472                                 speed = VectorLength(cl.movement_velocity);
8473
8474                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8475                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8476
8477                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8478                                 speed = bound(0, speed, 1);
8479                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8480
8481                                 // calculate values into a standard alpha
8482                                 cl.motionbluralpha = 1 - exp(-
8483                                                 (
8484                                                  (r_motionblur.value * speed / 80)
8485                                                  +
8486                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8487                                                 )
8488                                                 /
8489                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
8490                                            );
8491
8492                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8493                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8494                                 // apply the blur
8495                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8496                                 {
8497                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8498                                         GL_Color(1, 1, 1, cl.motionbluralpha);
8499                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8500                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
8501                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8502                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8503                                 }
8504                         }
8505
8506                         // copy view into the screen texture
8507                         R_Mesh_CopyToTexture(r_bloomstate.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8508                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8509                 }
8510                 else if (!r_bloomstate.texture_bloom)
8511                 {
8512                         // we may still have to do view tint...
8513                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8514                         {
8515                                 // apply a color tint to the whole view
8516                                 R_ResetViewRendering2D();
8517                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8518                                 R_Mesh_ColorPointer(NULL, 0, 0);
8519                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8520                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8521                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8522                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8523                         }
8524                         break; // no screen processing, no bloom, skip it
8525                 }
8526
8527                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8528                 {
8529                         // render simple bloom effect
8530                         // copy the screen and shrink it and darken it for the bloom process
8531                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8532                         // make the bloom texture
8533                         R_Bloom_MakeTexture();
8534                 }
8535
8536 #if _MSC_VER >= 1400
8537 #define sscanf sscanf_s
8538 #endif
8539                 memset(uservecs, 0, sizeof(uservecs));
8540                 if (r_glsl_postprocess_uservec1_enable.integer)
8541                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8542                 if (r_glsl_postprocess_uservec2_enable.integer)
8543                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8544                 if (r_glsl_postprocess_uservec3_enable.integer)
8545                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8546                 if (r_glsl_postprocess_uservec4_enable.integer)
8547                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8548
8549                 R_ResetViewRendering2D();
8550                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8551                 R_Mesh_ColorPointer(NULL, 0, 0);
8552                 GL_Color(1, 1, 1, 1);
8553                 GL_BlendFunc(GL_ONE, GL_ZERO);
8554                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
8555                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
8556
8557                 switch(vid.renderpath)
8558                 {
8559                 case RENDERPATH_GL20:
8560                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8561                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
8562                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
8563                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
8564                         if (r_glsl_permutation->loc_ViewTintColor      >= 0) qglUniform4fARB(r_glsl_permutation->loc_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8565                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8566                         if (r_glsl_permutation->loc_UserVec1           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8567                         if (r_glsl_permutation->loc_UserVec2           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8568                         if (r_glsl_permutation->loc_UserVec3           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8569                         if (r_glsl_permutation->loc_UserVec4           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8570                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
8571                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8572                         break;
8573                 case RENDERPATH_CGGL:
8574 #ifdef SUPPORTCG
8575                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
8576                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
8577                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
8578                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
8579                         if (r_cg_permutation->fp_ViewTintColor     ) cgGLSetParameter4f(     r_cg_permutation->fp_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);CHECKCGERROR
8580                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
8581                         if (r_cg_permutation->fp_UserVec1          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);CHECKCGERROR
8582                         if (r_cg_permutation->fp_UserVec2          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);CHECKCGERROR
8583                         if (r_cg_permutation->fp_UserVec3          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);CHECKCGERROR
8584                         if (r_cg_permutation->fp_UserVec4          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);CHECKCGERROR
8585                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
8586                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
8587 #endif
8588                         break;
8589                 default:
8590                         break;
8591                 }
8592                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8593                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8594                 break;
8595         case RENDERPATH_GL13:
8596         case RENDERPATH_GL11:
8597                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8598                 {
8599                         // apply a color tint to the whole view
8600                         R_ResetViewRendering2D();
8601                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8602                         R_Mesh_ColorPointer(NULL, 0, 0);
8603                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8604                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8605                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8606                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8607                 }
8608                 break;
8609         }
8610 }
8611
8612 matrix4x4_t r_waterscrollmatrix;
8613
8614 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8615 {
8616         if (r_refdef.fog_density)
8617         {
8618                 r_refdef.fogcolor[0] = r_refdef.fog_red;
8619                 r_refdef.fogcolor[1] = r_refdef.fog_green;
8620                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8621
8622                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8623                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
8624                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
8625                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
8626
8627                 {
8628                         vec3_t fogvec;
8629                         VectorCopy(r_refdef.fogcolor, fogvec);
8630                         //   color.rgb *= ContrastBoost * SceneBrightness;
8631                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
8632                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
8633                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
8634                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
8635                 }
8636         }
8637 }
8638
8639 void R_UpdateVariables(void)
8640 {
8641         R_Textures_Frame();
8642
8643         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8644
8645         r_refdef.farclip = r_farclip_base.value;
8646         if (r_refdef.scene.worldmodel)
8647                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8648         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8649
8650         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8651                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8652         r_refdef.polygonfactor = 0;
8653         r_refdef.polygonoffset = 0;
8654         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8655         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8656
8657         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8658         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8659         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
8660         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8661         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8662         if (FAKELIGHT_ENABLED)
8663         {
8664                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
8665         }
8666         if (r_showsurfaces.integer)
8667         {
8668                 r_refdef.scene.rtworld = false;
8669                 r_refdef.scene.rtworldshadows = false;
8670                 r_refdef.scene.rtdlight = false;
8671                 r_refdef.scene.rtdlightshadows = false;
8672                 r_refdef.lightmapintensity = 0;
8673         }
8674
8675         if (gamemode == GAME_NEHAHRA)
8676         {
8677                 if (gl_fogenable.integer)
8678                 {
8679                         r_refdef.oldgl_fogenable = true;
8680                         r_refdef.fog_density = gl_fogdensity.value;
8681                         r_refdef.fog_red = gl_fogred.value;
8682                         r_refdef.fog_green = gl_foggreen.value;
8683                         r_refdef.fog_blue = gl_fogblue.value;
8684                         r_refdef.fog_alpha = 1;
8685                         r_refdef.fog_start = 0;
8686                         r_refdef.fog_end = gl_skyclip.value;
8687                         r_refdef.fog_height = 1<<30;
8688                         r_refdef.fog_fadedepth = 128;
8689                 }
8690                 else if (r_refdef.oldgl_fogenable)
8691                 {
8692                         r_refdef.oldgl_fogenable = false;
8693                         r_refdef.fog_density = 0;
8694                         r_refdef.fog_red = 0;
8695                         r_refdef.fog_green = 0;
8696                         r_refdef.fog_blue = 0;
8697                         r_refdef.fog_alpha = 0;
8698                         r_refdef.fog_start = 0;
8699                         r_refdef.fog_end = 0;
8700                         r_refdef.fog_height = 1<<30;
8701                         r_refdef.fog_fadedepth = 128;
8702                 }
8703         }
8704
8705         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8706         r_refdef.fog_start = max(0, r_refdef.fog_start);
8707         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8708
8709         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8710
8711         if (r_refdef.fog_density && r_drawfog.integer)
8712         {
8713                 r_refdef.fogenabled = true;
8714                 // this is the point where the fog reaches 0.9986 alpha, which we
8715                 // consider a good enough cutoff point for the texture
8716                 // (0.9986 * 256 == 255.6)
8717                 if (r_fog_exp2.integer)
8718                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
8719                 else
8720                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
8721                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
8722                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
8723                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
8724                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
8725                         R_BuildFogHeightTexture();
8726                 // fog color was already set
8727                 // update the fog texture
8728                 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)
8729                         R_BuildFogTexture();
8730                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
8731                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
8732         }
8733         else
8734                 r_refdef.fogenabled = false;
8735
8736         switch(vid.renderpath)
8737         {
8738         case RENDERPATH_GL20:
8739         case RENDERPATH_CGGL:
8740                 if(v_glslgamma.integer && !vid_gammatables_trivial)
8741                 {
8742                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
8743                         {
8744                                 // build GLSL gamma texture
8745 #define RAMPWIDTH 256
8746                                 unsigned short ramp[RAMPWIDTH * 3];
8747                                 unsigned char rampbgr[RAMPWIDTH][4];
8748                                 int i;
8749
8750                                 r_texture_gammaramps_serial = vid_gammatables_serial;
8751
8752                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
8753                                 for(i = 0; i < RAMPWIDTH; ++i)
8754                                 {
8755                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8756                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8757                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
8758                                         rampbgr[i][3] = 0;
8759                                 }
8760                                 if (r_texture_gammaramps)
8761                                 {
8762                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
8763                                 }
8764                                 else
8765                                 {
8766                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
8767                                 }
8768                         }
8769                 }
8770                 else
8771                 {
8772                         // remove GLSL gamma texture
8773                 }
8774                 break;
8775         case RENDERPATH_GL13:
8776         case RENDERPATH_GL11:
8777                 break;
8778         }
8779 }
8780
8781 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
8782 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
8783 /*
8784 ================
8785 R_SelectScene
8786 ================
8787 */
8788 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
8789         if( scenetype != r_currentscenetype ) {
8790                 // store the old scenetype
8791                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
8792                 r_currentscenetype = scenetype;
8793                 // move in the new scene
8794                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
8795         }
8796 }
8797
8798 /*
8799 ================
8800 R_GetScenePointer
8801 ================
8802 */
8803 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
8804 {
8805         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
8806         if( scenetype == r_currentscenetype ) {
8807                 return &r_refdef.scene;
8808         } else {
8809                 return &r_scenes_store[ scenetype ];
8810         }
8811 }
8812
8813 /*
8814 ================
8815 R_RenderView
8816 ================
8817 */
8818 void R_RenderView(void)
8819 {
8820         if (r_timereport_active)
8821                 R_TimeReport("start");
8822         r_textureframe++; // used only by R_GetCurrentTexture
8823         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8824
8825         if(R_CompileShader_CheckStaticParms())
8826                 R_GLSL_Restart_f();
8827
8828         if (!r_drawentities.integer)
8829                 r_refdef.scene.numentities = 0;
8830
8831         R_AnimCache_ClearCache();
8832         R_FrameData_NewFrame();
8833
8834         if (r_refdef.view.isoverlay)
8835         {
8836                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
8837                 GL_Clear( GL_DEPTH_BUFFER_BIT );
8838                 R_TimeReport("depthclear");
8839
8840                 r_refdef.view.showdebug = false;
8841
8842                 r_waterstate.enabled = false;
8843                 r_waterstate.numwaterplanes = 0;
8844
8845                 R_RenderScene();
8846
8847                 CHECKGLERROR
8848                 return;
8849         }
8850
8851         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
8852                 return; //Host_Error ("R_RenderView: NULL worldmodel");
8853
8854         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
8855
8856         R_RenderView_UpdateViewVectors();
8857
8858         R_Shadow_UpdateWorldLightSelection();
8859
8860         R_Bloom_StartFrame();
8861         R_Water_StartFrame();
8862
8863         CHECKGLERROR
8864         if (r_timereport_active)
8865                 R_TimeReport("viewsetup");
8866
8867         R_ResetViewRendering3D();
8868
8869         if (r_refdef.view.clear || r_refdef.fogenabled)
8870         {
8871                 R_ClearScreen(r_refdef.fogenabled);
8872                 if (r_timereport_active)
8873                         R_TimeReport("viewclear");
8874         }
8875         r_refdef.view.clear = true;
8876
8877         // this produces a bloom texture to be used in R_BlendView() later
8878         if (r_hdr.integer && r_bloomstate.bloomwidth)
8879         {
8880                 R_HDR_RenderBloomTexture();
8881                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
8882                 r_textureframe++; // used only by R_GetCurrentTexture
8883         }
8884
8885         r_refdef.view.showdebug = true;
8886
8887         R_View_Update();
8888         if (r_timereport_active)
8889                 R_TimeReport("visibility");
8890
8891         r_waterstate.numwaterplanes = 0;
8892         if (r_waterstate.enabled)
8893                 R_RenderWaterPlanes();
8894
8895         R_RenderScene();
8896         r_waterstate.numwaterplanes = 0;
8897
8898         R_BlendView();
8899         if (r_timereport_active)
8900                 R_TimeReport("blendview");
8901
8902         GL_Scissor(0, 0, vid.width, vid.height);
8903         GL_ScissorTest(false);
8904
8905         CHECKGLERROR
8906 }
8907
8908 void R_RenderWaterPlanes(void)
8909 {
8910         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
8911         {
8912                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
8913                 if (r_timereport_active)
8914                         R_TimeReport("waterworld");
8915         }
8916
8917         // don't let sound skip if going slow
8918         if (r_refdef.scene.extraupdate)
8919                 S_ExtraUpdate ();
8920
8921         R_DrawModelsAddWaterPlanes();
8922         if (r_timereport_active)
8923                 R_TimeReport("watermodels");
8924
8925         if (r_waterstate.numwaterplanes)
8926         {
8927                 R_Water_ProcessPlanes();
8928                 if (r_timereport_active)
8929                         R_TimeReport("waterscenes");
8930         }
8931 }
8932
8933 extern void R_DrawLightningBeams (void);
8934 extern void VM_CL_AddPolygonsToMeshQueue (void);
8935 extern void R_DrawPortals (void);
8936 extern cvar_t cl_locs_show;
8937 static void R_DrawLocs(void);
8938 static void R_DrawEntityBBoxes(void);
8939 static void R_DrawModelDecals(void);
8940 extern void R_DrawModelShadows(void);
8941 extern void R_DrawModelShadowMaps(void);
8942 extern cvar_t cl_decals_newsystem;
8943 extern qboolean r_shadow_usingdeferredprepass;
8944 void R_RenderScene(void)
8945 {
8946         qboolean shadowmapping = false;
8947
8948         if (r_timereport_active)
8949                 R_TimeReport("beginscene");
8950
8951         r_refdef.stats.renders++;
8952
8953         R_UpdateFogColor();
8954
8955         // don't let sound skip if going slow
8956         if (r_refdef.scene.extraupdate)
8957                 S_ExtraUpdate ();
8958
8959         R_MeshQueue_BeginScene();
8960
8961         R_SkyStartFrame();
8962
8963         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);
8964
8965         if (r_timereport_active)
8966                 R_TimeReport("skystartframe");
8967
8968         if (cl.csqc_vidvars.drawworld)
8969         {
8970                 // don't let sound skip if going slow
8971                 if (r_refdef.scene.extraupdate)
8972                         S_ExtraUpdate ();
8973
8974                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
8975                 {
8976                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
8977                         if (r_timereport_active)
8978                                 R_TimeReport("worldsky");
8979                 }
8980
8981                 if (R_DrawBrushModelsSky() && r_timereport_active)
8982                         R_TimeReport("bmodelsky");
8983
8984                 if (skyrendermasked && skyrenderlater)
8985                 {
8986                         // we have to force off the water clipping plane while rendering sky
8987                         R_SetupView(false);
8988                         R_Sky();
8989                         R_SetupView(true);
8990                         if (r_timereport_active)
8991                                 R_TimeReport("sky");
8992                 }
8993         }
8994
8995         R_AnimCache_CacheVisibleEntities();
8996         if (r_timereport_active)
8997                 R_TimeReport("animation");
8998
8999         R_Shadow_PrepareLights();
9000         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9001                 R_Shadow_PrepareModelShadows();
9002         if (r_timereport_active)
9003                 R_TimeReport("preparelights");
9004
9005         if (R_Shadow_ShadowMappingEnabled())
9006                 shadowmapping = true;
9007
9008         if (r_shadow_usingdeferredprepass)
9009                 R_Shadow_DrawPrepass();
9010
9011         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9012         {
9013                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9014                 if (r_timereport_active)
9015                         R_TimeReport("worlddepth");
9016         }
9017         if (r_depthfirst.integer >= 2)
9018         {
9019                 R_DrawModelsDepth();
9020                 if (r_timereport_active)
9021                         R_TimeReport("modeldepth");
9022         }
9023
9024         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9025         {
9026                 R_DrawModelShadowMaps();
9027                 R_ResetViewRendering3D();
9028                 // don't let sound skip if going slow
9029                 if (r_refdef.scene.extraupdate)
9030                         S_ExtraUpdate ();
9031         }
9032
9033         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9034         {
9035                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9036                 if (r_timereport_active)
9037                         R_TimeReport("world");
9038         }
9039
9040         // don't let sound skip if going slow
9041         if (r_refdef.scene.extraupdate)
9042                 S_ExtraUpdate ();
9043
9044         R_DrawModels();
9045         if (r_timereport_active)
9046                 R_TimeReport("models");
9047
9048         // don't let sound skip if going slow
9049         if (r_refdef.scene.extraupdate)
9050                 S_ExtraUpdate ();
9051
9052         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9053         {
9054                 R_DrawModelShadows();
9055                 R_ResetViewRendering3D();
9056                 // don't let sound skip if going slow
9057                 if (r_refdef.scene.extraupdate)
9058                         S_ExtraUpdate ();
9059         }
9060
9061         if (!r_shadow_usingdeferredprepass)
9062         {
9063                 R_Shadow_DrawLights();
9064                 if (r_timereport_active)
9065                         R_TimeReport("rtlights");
9066         }
9067
9068         // don't let sound skip if going slow
9069         if (r_refdef.scene.extraupdate)
9070                 S_ExtraUpdate ();
9071
9072         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9073         {
9074                 R_DrawModelShadows();
9075                 R_ResetViewRendering3D();
9076                 // don't let sound skip if going slow
9077                 if (r_refdef.scene.extraupdate)
9078                         S_ExtraUpdate ();
9079         }
9080
9081         if (cl.csqc_vidvars.drawworld)
9082         {
9083                 if (cl_decals_newsystem.integer)
9084                 {
9085                         R_DrawModelDecals();
9086                         if (r_timereport_active)
9087                                 R_TimeReport("modeldecals");
9088                 }
9089                 else
9090                 {
9091                         R_DrawDecals();
9092                         if (r_timereport_active)
9093                                 R_TimeReport("decals");
9094                 }
9095
9096                 R_DrawParticles();
9097                 if (r_timereport_active)
9098                         R_TimeReport("particles");
9099
9100                 R_DrawExplosions();
9101                 if (r_timereport_active)
9102                         R_TimeReport("explosions");
9103
9104                 R_DrawLightningBeams();
9105                 if (r_timereport_active)
9106                         R_TimeReport("lightning");
9107         }
9108
9109         VM_CL_AddPolygonsToMeshQueue();
9110
9111         if (r_refdef.view.showdebug)
9112         {
9113                 if (cl_locs_show.integer)
9114                 {
9115                         R_DrawLocs();
9116                         if (r_timereport_active)
9117                                 R_TimeReport("showlocs");
9118                 }
9119
9120                 if (r_drawportals.integer)
9121                 {
9122                         R_DrawPortals();
9123                         if (r_timereport_active)
9124                                 R_TimeReport("portals");
9125                 }
9126
9127                 if (r_showbboxes.value > 0)
9128                 {
9129                         R_DrawEntityBBoxes();
9130                         if (r_timereport_active)
9131                                 R_TimeReport("bboxes");
9132                 }
9133         }
9134
9135         R_MeshQueue_RenderTransparent();
9136         if (r_timereport_active)
9137                 R_TimeReport("drawtrans");
9138
9139         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))
9140         {
9141                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9142                 if (r_timereport_active)
9143                         R_TimeReport("worlddebug");
9144                 R_DrawModelsDebug();
9145                 if (r_timereport_active)
9146                         R_TimeReport("modeldebug");
9147         }
9148
9149         if (cl.csqc_vidvars.drawworld)
9150         {
9151                 R_Shadow_DrawCoronas();
9152                 if (r_timereport_active)
9153                         R_TimeReport("coronas");
9154         }
9155
9156 #if 0
9157         {
9158                 GL_DepthTest(false);
9159                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9160                 GL_Color(1, 1, 1, 1);
9161                 qglBegin(GL_POLYGON);
9162                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9163                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9164                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9165                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9166                 qglEnd();
9167                 qglBegin(GL_POLYGON);
9168                 qglVertex3f(r_refdef.view.frustumcorner[0][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[0][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[0][2] + 1000 * r_refdef.view.forward[2]);
9169                 qglVertex3f(r_refdef.view.frustumcorner[1][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[1][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[1][2] + 1000 * r_refdef.view.forward[2]);
9170                 qglVertex3f(r_refdef.view.frustumcorner[3][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[3][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[3][2] + 1000 * r_refdef.view.forward[2]);
9171                 qglVertex3f(r_refdef.view.frustumcorner[2][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[2][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[2][2] + 1000 * r_refdef.view.forward[2]);
9172                 qglEnd();
9173                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9174         }
9175 #endif
9176
9177         // don't let sound skip if going slow
9178         if (r_refdef.scene.extraupdate)
9179                 S_ExtraUpdate ();
9180
9181         R_ResetViewRendering2D();
9182 }
9183
9184 static const unsigned short bboxelements[36] =
9185 {
9186         5, 1, 3, 5, 3, 7,
9187         6, 2, 0, 6, 0, 4,
9188         7, 3, 2, 7, 2, 6,
9189         4, 0, 1, 4, 1, 5,
9190         4, 5, 7, 4, 7, 6,
9191         1, 0, 2, 1, 2, 3,
9192 };
9193
9194 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9195 {
9196         int i;
9197         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9198
9199         RSurf_ActiveWorldEntity();
9200
9201         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9202         GL_DepthMask(false);
9203         GL_DepthRange(0, 1);
9204         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9205         R_Mesh_ResetTextureState();
9206
9207         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9208         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9209         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9210         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9211         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9212         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9213         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9214         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9215         R_FillColors(color4f, 8, cr, cg, cb, ca);
9216         if (r_refdef.fogenabled)
9217         {
9218                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9219                 {
9220                         f1 = RSurf_FogVertex(v);
9221                         f2 = 1 - f1;
9222                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9223                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9224                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9225                 }
9226         }
9227         R_Mesh_VertexPointer(vertex3f, 0, 0);
9228         R_Mesh_ColorPointer(color4f, 0, 0);
9229         R_Mesh_ResetTextureState();
9230         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9231         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
9232 }
9233
9234 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9235 {
9236         int i;
9237         float color[4];
9238         prvm_edict_t *edict;
9239         prvm_prog_t *prog_save = prog;
9240
9241         // this function draws bounding boxes of server entities
9242         if (!sv.active)
9243                 return;
9244
9245         GL_CullFace(GL_NONE);
9246         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9247
9248         prog = 0;
9249         SV_VM_Begin();
9250         for (i = 0;i < numsurfaces;i++)
9251         {
9252                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9253                 switch ((int)edict->fields.server->solid)
9254                 {
9255                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9256                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9257                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9258                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9259                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9260                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9261                 }
9262                 color[3] *= r_showbboxes.value;
9263                 color[3] = bound(0, color[3], 1);
9264                 GL_DepthTest(!r_showdisabledepthtest.integer);
9265                 GL_CullFace(r_refdef.view.cullface_front);
9266                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9267         }
9268         SV_VM_End();
9269         prog = prog_save;
9270 }
9271
9272 static void R_DrawEntityBBoxes(void)
9273 {
9274         int i;
9275         prvm_edict_t *edict;
9276         vec3_t center;
9277         prvm_prog_t *prog_save = prog;
9278
9279         // this function draws bounding boxes of server entities
9280         if (!sv.active)
9281                 return;
9282
9283         prog = 0;
9284         SV_VM_Begin();
9285         for (i = 0;i < prog->num_edicts;i++)
9286         {
9287                 edict = PRVM_EDICT_NUM(i);
9288                 if (edict->priv.server->free)
9289                         continue;
9290                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9291                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9292                         continue;
9293                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9294                         continue;
9295                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9296                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9297         }
9298         SV_VM_End();
9299         prog = prog_save;
9300 }
9301
9302 static const int nomodelelement3i[24] =
9303 {
9304         5, 2, 0,
9305         5, 1, 2,
9306         5, 0, 3,
9307         5, 3, 1,
9308         0, 2, 4,
9309         2, 1, 4,
9310         3, 0, 4,
9311         1, 3, 4
9312 };
9313
9314 static const unsigned short nomodelelement3s[24] =
9315 {
9316         5, 2, 0,
9317         5, 1, 2,
9318         5, 0, 3,
9319         5, 3, 1,
9320         0, 2, 4,
9321         2, 1, 4,
9322         3, 0, 4,
9323         1, 3, 4
9324 };
9325
9326 static const float nomodelvertex3f[6*3] =
9327 {
9328         -16,   0,   0,
9329          16,   0,   0,
9330           0, -16,   0,
9331           0,  16,   0,
9332           0,   0, -16,
9333           0,   0,  16
9334 };
9335
9336 static const float nomodelcolor4f[6*4] =
9337 {
9338         0.0f, 0.0f, 0.5f, 1.0f,
9339         0.0f, 0.0f, 0.5f, 1.0f,
9340         0.0f, 0.5f, 0.0f, 1.0f,
9341         0.0f, 0.5f, 0.0f, 1.0f,
9342         0.5f, 0.0f, 0.0f, 1.0f,
9343         0.5f, 0.0f, 0.0f, 1.0f
9344 };
9345
9346 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9347 {
9348         int i;
9349         float f1, f2, *c;
9350         float color4f[6*4];
9351
9352         RSurf_ActiveCustomEntity(&ent->matrix, &ent->inversematrix, ent->flags, ent->shadertime, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha, 6, nomodelvertex3f, NULL, NULL, NULL, NULL, nomodelcolor4f, 8, nomodelelement3i, nomodelelement3s, false, false);
9353
9354         // this is only called once per entity so numsurfaces is always 1, and
9355         // surfacelist is always {0}, so this code does not handle batches
9356
9357         if (rsurface.ent_flags & RENDER_ADDITIVE)
9358         {
9359                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9360                 GL_DepthMask(false);
9361         }
9362         else if (rsurface.colormod[3] < 1)
9363         {
9364                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9365                 GL_DepthMask(false);
9366         }
9367         else
9368         {
9369                 GL_BlendFunc(GL_ONE, GL_ZERO);
9370                 GL_DepthMask(true);
9371         }
9372         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9373         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9374         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9375         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9376         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9377         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9378         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9379         R_Mesh_ColorPointer(color4f, 0, 0);
9380         for (i = 0, c = color4f;i < 6;i++, c += 4)
9381         {
9382                 c[0] *= rsurface.colormod[0];
9383                 c[1] *= rsurface.colormod[1];
9384                 c[2] *= rsurface.colormod[2];
9385                 c[3] *= rsurface.colormod[3];
9386         }
9387         if (r_refdef.fogenabled)
9388         {
9389                 for (i = 0, c = color4f;i < 6;i++, c += 4)
9390                 {
9391                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
9392                         f2 = 1 - f1;
9393                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9394                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9395                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9396                 }
9397         }
9398         R_Mesh_ResetTextureState();
9399         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
9400 }
9401
9402 void R_DrawNoModel(entity_render_t *ent)
9403 {
9404         vec3_t org;
9405         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9406         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9407                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9408         else
9409                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9410 }
9411
9412 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9413 {
9414         vec3_t right1, right2, diff, normal;
9415
9416         VectorSubtract (org2, org1, normal);
9417
9418         // calculate 'right' vector for start
9419         VectorSubtract (r_refdef.view.origin, org1, diff);
9420         CrossProduct (normal, diff, right1);
9421         VectorNormalize (right1);
9422
9423         // calculate 'right' vector for end
9424         VectorSubtract (r_refdef.view.origin, org2, diff);
9425         CrossProduct (normal, diff, right2);
9426         VectorNormalize (right2);
9427
9428         vert[ 0] = org1[0] + width * right1[0];
9429         vert[ 1] = org1[1] + width * right1[1];
9430         vert[ 2] = org1[2] + width * right1[2];
9431         vert[ 3] = org1[0] - width * right1[0];
9432         vert[ 4] = org1[1] - width * right1[1];
9433         vert[ 5] = org1[2] - width * right1[2];
9434         vert[ 6] = org2[0] - width * right2[0];
9435         vert[ 7] = org2[1] - width * right2[1];
9436         vert[ 8] = org2[2] - width * right2[2];
9437         vert[ 9] = org2[0] + width * right2[0];
9438         vert[10] = org2[1] + width * right2[1];
9439         vert[11] = org2[2] + width * right2[2];
9440 }
9441
9442 void R_CalcSprite_Vertex3f(float *vertex3f, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2)
9443 {
9444         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9445         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9446         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9447         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9448         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9449         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9450         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9451         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9452         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9453         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9454         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9455         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9456 }
9457
9458 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9459 {
9460         int i;
9461         float *vertex3f;
9462         float v[3];
9463         VectorSet(v, x, y, z);
9464         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9465                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9466                         break;
9467         if (i == mesh->numvertices)
9468         {
9469                 if (mesh->numvertices < mesh->maxvertices)
9470                 {
9471                         VectorCopy(v, vertex3f);
9472                         mesh->numvertices++;
9473                 }
9474                 return mesh->numvertices;
9475         }
9476         else
9477                 return i;
9478 }
9479
9480 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9481 {
9482         int i;
9483         int *e, element[3];
9484         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9485         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9486         e = mesh->element3i + mesh->numtriangles * 3;
9487         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9488         {
9489                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9490                 if (mesh->numtriangles < mesh->maxtriangles)
9491                 {
9492                         *e++ = element[0];
9493                         *e++ = element[1];
9494                         *e++ = element[2];
9495                         mesh->numtriangles++;
9496                 }
9497                 element[1] = element[2];
9498         }
9499 }
9500
9501 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9502 {
9503         int i;
9504         int *e, element[3];
9505         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9506         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9507         e = mesh->element3i + mesh->numtriangles * 3;
9508         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9509         {
9510                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9511                 if (mesh->numtriangles < mesh->maxtriangles)
9512                 {
9513                         *e++ = element[0];
9514                         *e++ = element[1];
9515                         *e++ = element[2];
9516                         mesh->numtriangles++;
9517                 }
9518                 element[1] = element[2];
9519         }
9520 }
9521
9522 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9523 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9524 {
9525         int planenum, planenum2;
9526         int w;
9527         int tempnumpoints;
9528         mplane_t *plane, *plane2;
9529         double maxdist;
9530         double temppoints[2][256*3];
9531         // figure out how large a bounding box we need to properly compute this brush
9532         maxdist = 0;
9533         for (w = 0;w < numplanes;w++)
9534                 maxdist = max(maxdist, fabs(planes[w].dist));
9535         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9536         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9537         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9538         {
9539                 w = 0;
9540                 tempnumpoints = 4;
9541                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9542                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9543                 {
9544                         if (planenum2 == planenum)
9545                                 continue;
9546                         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);
9547                         w = !w;
9548                 }
9549                 if (tempnumpoints < 3)
9550                         continue;
9551                 // generate elements forming a triangle fan for this polygon
9552                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9553         }
9554 }
9555
9556 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)
9557 {
9558         texturelayer_t *layer;
9559         layer = t->currentlayers + t->currentnumlayers++;
9560         layer->type = type;
9561         layer->depthmask = depthmask;
9562         layer->blendfunc1 = blendfunc1;
9563         layer->blendfunc2 = blendfunc2;
9564         layer->texture = texture;
9565         layer->texmatrix = *matrix;
9566         layer->color[0] = r;
9567         layer->color[1] = g;
9568         layer->color[2] = b;
9569         layer->color[3] = a;
9570 }
9571
9572 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
9573 {
9574         if(parms[0] == 0 && parms[1] == 0)
9575                 return false;
9576         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9577                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
9578                         return false;
9579         return true;
9580 }
9581
9582 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
9583 {
9584         double index, f;
9585         index = parms[2] + r_refdef.scene.time * parms[3];
9586         index -= floor(index);
9587         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
9588         {
9589         default:
9590         case Q3WAVEFUNC_NONE:
9591         case Q3WAVEFUNC_NOISE:
9592         case Q3WAVEFUNC_COUNT:
9593                 f = 0;
9594                 break;
9595         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
9596         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
9597         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
9598         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
9599         case Q3WAVEFUNC_TRIANGLE:
9600                 index *= 4;
9601                 f = index - floor(index);
9602                 if (index < 1)
9603                         f = f;
9604                 else if (index < 2)
9605                         f = 1 - f;
9606                 else if (index < 3)
9607                         f = -f;
9608                 else
9609                         f = -(1 - f);
9610                 break;
9611         }
9612         f = parms[0] + parms[1] * f;
9613         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9614                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
9615         return (float) f;
9616 }
9617
9618 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
9619 {
9620         int w, h, idx;
9621         float f;
9622         float tcmat[12];
9623         matrix4x4_t matrix, temp;
9624         switch(tcmod->tcmod)
9625         {
9626                 case Q3TCMOD_COUNT:
9627                 case Q3TCMOD_NONE:
9628                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9629                                 matrix = r_waterscrollmatrix;
9630                         else
9631                                 matrix = identitymatrix;
9632                         break;
9633                 case Q3TCMOD_ENTITYTRANSLATE:
9634                         // this is used in Q3 to allow the gamecode to control texcoord
9635                         // scrolling on the entity, which is not supported in darkplaces yet.
9636                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
9637                         break;
9638                 case Q3TCMOD_ROTATE:
9639                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
9640                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
9641                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
9642                         break;
9643                 case Q3TCMOD_SCALE:
9644                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
9645                         break;
9646                 case Q3TCMOD_SCROLL:
9647                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
9648                         break;
9649                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
9650                         w = (int) tcmod->parms[0];
9651                         h = (int) tcmod->parms[1];
9652                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
9653                         f = f - floor(f);
9654                         idx = (int) floor(f * w * h);
9655                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
9656                         break;
9657                 case Q3TCMOD_STRETCH:
9658                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
9659                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
9660                         break;
9661                 case Q3TCMOD_TRANSFORM:
9662                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
9663                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
9664                         VectorSet(tcmat +  6, 0                   , 0                , 1);
9665                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
9666                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
9667                         break;
9668                 case Q3TCMOD_TURBULENT:
9669                         // this is handled in the RSurf_PrepareVertices function
9670                         matrix = identitymatrix;
9671                         break;
9672         }
9673         temp = *texmatrix;
9674         Matrix4x4_Concat(texmatrix, &matrix, &temp);
9675 }
9676
9677 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
9678 {
9679         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
9680         char name[MAX_QPATH];
9681         skinframe_t *skinframe;
9682         unsigned char pixels[296*194];
9683         strlcpy(cache->name, skinname, sizeof(cache->name));
9684         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
9685         if (developer_loading.integer)
9686                 Con_Printf("loading %s\n", name);
9687         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
9688         if (!skinframe || !skinframe->base)
9689         {
9690                 unsigned char *f;
9691                 fs_offset_t filesize;
9692                 skinframe = NULL;
9693                 f = FS_LoadFile(name, tempmempool, true, &filesize);
9694                 if (f)
9695                 {
9696                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
9697                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
9698                         Mem_Free(f);
9699                 }
9700         }
9701         cache->skinframe = skinframe;
9702 }
9703
9704 texture_t *R_GetCurrentTexture(texture_t *t)
9705 {
9706         int i;
9707         const entity_render_t *ent = rsurface.entity;
9708         dp_model_t *model = ent->model;
9709         q3shaderinfo_layer_tcmod_t *tcmod;
9710
9711         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
9712                 return t->currentframe;
9713         t->update_lastrenderframe = r_textureframe;
9714         t->update_lastrenderentity = (void *)ent;
9715
9716         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
9717                 t->camera_entity = ent->entitynumber;
9718         else
9719                 t->camera_entity = 0;
9720
9721         // switch to an alternate material if this is a q1bsp animated material
9722         {
9723                 texture_t *texture = t;
9724                 int s = rsurface.ent_skinnum;
9725                 if ((unsigned int)s >= (unsigned int)model->numskins)
9726                         s = 0;
9727                 if (model->skinscenes)
9728                 {
9729                         if (model->skinscenes[s].framecount > 1)
9730                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
9731                         else
9732                                 s = model->skinscenes[s].firstframe;
9733                 }
9734                 if (s > 0)
9735                         t = t + s * model->num_surfaces;
9736                 if (t->animated)
9737                 {
9738                         // use an alternate animation if the entity's frame is not 0,
9739                         // and only if the texture has an alternate animation
9740                         if (rsurface.ent_alttextures && t->anim_total[1])
9741                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
9742                         else
9743                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
9744                 }
9745                 texture->currentframe = t;
9746         }
9747
9748         // update currentskinframe to be a qw skin or animation frame
9749         if (rsurface.ent_qwskin >= 0)
9750         {
9751                 i = rsurface.ent_qwskin;
9752                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
9753                 {
9754                         r_qwskincache_size = cl.maxclients;
9755                         if (r_qwskincache)
9756                                 Mem_Free(r_qwskincache);
9757                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
9758                 }
9759                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
9760                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
9761                 t->currentskinframe = r_qwskincache[i].skinframe;
9762                 if (t->currentskinframe == NULL)
9763                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9764         }
9765         else if (t->numskinframes >= 2)
9766                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9767         if (t->backgroundnumskinframes >= 2)
9768                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
9769
9770         t->currentmaterialflags = t->basematerialflags;
9771         t->currentalpha = rsurface.colormod[3];
9772         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
9773                 t->currentalpha *= r_wateralpha.value;
9774         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
9775                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
9776         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
9777                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
9778         if (!(rsurface.ent_flags & RENDER_LIGHT))
9779                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
9780         else if (FAKELIGHT_ENABLED)
9781         {
9782                         // no modellight if using fakelight for the map
9783         }
9784         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
9785         {
9786                 // pick a model lighting mode
9787                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
9788                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
9789                 else
9790                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
9791         }
9792         if (rsurface.ent_flags & RENDER_ADDITIVE)
9793                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9794         else if (t->currentalpha < 1)
9795                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9796         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
9797                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
9798         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
9799                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
9800         if (t->backgroundnumskinframes)
9801                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
9802         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
9803         {
9804                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
9805                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
9806         }
9807         else
9808                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
9809         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
9810                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
9811
9812         // there is no tcmod
9813         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9814         {
9815                 t->currenttexmatrix = r_waterscrollmatrix;
9816                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
9817         }
9818         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
9819         {
9820                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
9821                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
9822         }
9823
9824         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9825                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
9826         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9827                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
9828
9829         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
9830         if (t->currentskinframe->qpixels)
9831                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
9832         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
9833         if (!t->basetexture)
9834                 t->basetexture = r_texture_notexture;
9835         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
9836         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
9837         t->nmaptexture = t->currentskinframe->nmap;
9838         if (!t->nmaptexture)
9839                 t->nmaptexture = r_texture_blanknormalmap;
9840         t->glosstexture = r_texture_black;
9841         t->glowtexture = t->currentskinframe->glow;
9842         t->fogtexture = t->currentskinframe->fog;
9843         t->reflectmasktexture = t->currentskinframe->reflect;
9844         if (t->backgroundnumskinframes)
9845         {
9846                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9847                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9848                 t->backgroundglosstexture = r_texture_black;
9849                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9850                 if (!t->backgroundnmaptexture)
9851                         t->backgroundnmaptexture = r_texture_blanknormalmap;
9852         }
9853         else
9854         {
9855                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
9856                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9857                 t->backgroundglosstexture = r_texture_black;
9858                 t->backgroundglowtexture = NULL;
9859         }
9860         t->specularpower = r_shadow_glossexponent.value;
9861         // TODO: store reference values for these in the texture?
9862         t->specularscale = 0;
9863         if (r_shadow_gloss.integer > 0)
9864         {
9865                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9866                 {
9867                         if (r_shadow_glossintensity.value > 0)
9868                         {
9869                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9870                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9871                                 t->specularscale = r_shadow_glossintensity.value;
9872                         }
9873                 }
9874                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9875                 {
9876                         t->glosstexture = r_texture_white;
9877                         t->backgroundglosstexture = r_texture_white;
9878                         t->specularscale = r_shadow_gloss2intensity.value;
9879                         t->specularpower = r_shadow_gloss2exponent.value;
9880                 }
9881         }
9882         t->specularscale *= t->specularscalemod;
9883         t->specularpower *= t->specularpowermod;
9884
9885         // lightmaps mode looks bad with dlights using actual texturing, so turn
9886         // off the colormap and glossmap, but leave the normalmap on as it still
9887         // accurately represents the shading involved
9888         if (gl_lightmaps.integer)
9889         {
9890                 t->basetexture = r_texture_grey128;
9891                 t->pantstexture = r_texture_black;
9892                 t->shirttexture = r_texture_black;
9893                 t->nmaptexture = r_texture_blanknormalmap;
9894                 t->glosstexture = r_texture_black;
9895                 t->glowtexture = NULL;
9896                 t->fogtexture = NULL;
9897                 t->reflectmasktexture = NULL;
9898                 t->backgroundbasetexture = NULL;
9899                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9900                 t->backgroundglosstexture = r_texture_black;
9901                 t->backgroundglowtexture = NULL;
9902                 t->specularscale = 0;
9903                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9904         }
9905
9906         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9907         VectorClear(t->dlightcolor);
9908         t->currentnumlayers = 0;
9909         if (t->currentmaterialflags & MATERIALFLAG_WALL)
9910         {
9911                 int blendfunc1, blendfunc2;
9912                 qboolean depthmask;
9913                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9914                 {
9915                         blendfunc1 = GL_SRC_ALPHA;
9916                         blendfunc2 = GL_ONE;
9917                 }
9918                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9919                 {
9920                         blendfunc1 = GL_SRC_ALPHA;
9921                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9922                 }
9923                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9924                 {
9925                         blendfunc1 = t->customblendfunc[0];
9926                         blendfunc2 = t->customblendfunc[1];
9927                 }
9928                 else
9929                 {
9930                         blendfunc1 = GL_ONE;
9931                         blendfunc2 = GL_ZERO;
9932                 }
9933                 // don't colormod evilblend textures
9934                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
9935                         VectorSet(t->lightmapcolor, 1, 1, 1);
9936                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9937                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9938                 {
9939                         // fullbright is not affected by r_refdef.lightmapintensity
9940                         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]);
9941                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9942                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
9943                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9944                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
9945                 }
9946                 else
9947                 {
9948                         vec3_t ambientcolor;
9949                         float colorscale;
9950                         // set the color tint used for lights affecting this surface
9951                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9952                         colorscale = 2;
9953                         // q3bsp has no lightmap updates, so the lightstylevalue that
9954                         // would normally be baked into the lightmap must be
9955                         // applied to the color
9956                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9957                         if (model->type == mod_brushq3)
9958                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9959                         colorscale *= r_refdef.lightmapintensity;
9960                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9961                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9962                         // basic lit geometry
9963                         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]);
9964                         // add pants/shirt if needed
9965                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9966                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2]  * t->lightmapcolor[2], t->lightmapcolor[3]);
9967                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9968                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
9969                         // now add ambient passes if needed
9970                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9971                         {
9972                                 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]);
9973                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9974                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
9975                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9976                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
9977                         }
9978                 }
9979                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9980                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]);
9981                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9982                 {
9983                         // if this is opaque use alpha blend which will darken the earlier
9984                         // passes cheaply.
9985                         //
9986                         // if this is an alpha blended material, all the earlier passes
9987                         // were darkened by fog already, so we only need to add the fog
9988                         // color ontop through the fog mask texture
9989                         //
9990                         // if this is an additive blended material, all the earlier passes
9991                         // were darkened by fog already, and we should not add fog color
9992                         // (because the background was not darkened, there is no fog color
9993                         // that was lost behind it).
9994                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->lightmapcolor[3]);
9995                 }
9996         }
9997
9998         return t->currentframe;
9999 }
10000
10001 rsurfacestate_t rsurface;
10002
10003 void R_Mesh_ResizeArrays(int newvertices)
10004 {
10005         float *base;
10006         if (rsurface.array_size >= newvertices)
10007                 return;
10008         if (rsurface.array_modelvertex3f)
10009                 Mem_Free(rsurface.array_modelvertex3f);
10010         rsurface.array_size = (newvertices + 1023) & ~1023;
10011         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
10012         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
10013         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
10014         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
10015         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
10016         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
10017         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
10018         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
10019         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
10020         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
10021         rsurface.array_color4f           = base + rsurface.array_size * 27;
10022         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
10023 }
10024
10025 void RSurf_ActiveWorldEntity(void)
10026 {
10027         dp_model_t *model = r_refdef.scene.worldmodel;
10028         //if (rsurface.entity == r_refdef.scene.worldentity)
10029         //      return;
10030         rsurface.entity = r_refdef.scene.worldentity;
10031         rsurface.skeleton = NULL;
10032         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10033         rsurface.ent_skinnum = 0;
10034         rsurface.ent_qwskin = -1;
10035         rsurface.ent_shadertime = 0;
10036         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10037         if (rsurface.array_size < model->surfmesh.num_vertices)
10038                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10039         rsurface.matrix = identitymatrix;
10040         rsurface.inversematrix = identitymatrix;
10041         rsurface.matrixscale = 1;
10042         rsurface.inversematrixscale = 1;
10043         R_EntityMatrix(&identitymatrix);
10044         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10045         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10046         rsurface.fograngerecip = r_refdef.fograngerecip;
10047         rsurface.fogheightfade = r_refdef.fogheightfade;
10048         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10049         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10050         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10051         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10052         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10053         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10054         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10055         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10056         rsurface.colormod[3] = 1;
10057         VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
10058         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10059         rsurface.frameblend[0].lerp = 1;
10060         rsurface.ent_alttextures = false;
10061         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10062         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10063         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10064         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
10065         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10066         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10067         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
10068         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10069         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10070         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
10071         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10072         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10073         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
10074         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10075         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10076         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
10077         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10078         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10079         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
10080         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10081         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10082         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
10083         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10084         rsurface.modelelement3i = model->surfmesh.data_element3i;
10085         rsurface.modelelement3s = model->surfmesh.data_element3s;
10086         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
10087         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
10088         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10089         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
10090         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
10091         rsurface.modelsurfaces = model->data_surfaces;
10092         rsurface.generatedvertex = false;
10093         rsurface.vertex3f  = rsurface.modelvertex3f;
10094         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
10095         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10096         rsurface.svector3f = rsurface.modelsvector3f;
10097         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
10098         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10099         rsurface.tvector3f = rsurface.modeltvector3f;
10100         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
10101         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10102         rsurface.normal3f  = rsurface.modelnormal3f;
10103         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
10104         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10105         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
10106 }
10107
10108 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10109 {
10110         dp_model_t *model = ent->model;
10111         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10112         //      return;
10113         rsurface.entity = (entity_render_t *)ent;
10114         rsurface.skeleton = ent->skeleton;
10115         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10116         rsurface.ent_skinnum = ent->skinnum;
10117         rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1;
10118         rsurface.ent_shadertime = ent->shadertime;
10119         rsurface.ent_flags = ent->flags;
10120         if (rsurface.array_size < model->surfmesh.num_vertices)
10121                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10122         rsurface.matrix = ent->matrix;
10123         rsurface.inversematrix = ent->inversematrix;
10124         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10125         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10126         R_EntityMatrix(&rsurface.matrix);
10127         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10128         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10129         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10130         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10131         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10132         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10133         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10134         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10135         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10136         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10137         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10138         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10139         rsurface.colormod[3] = ent->alpha;
10140         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10141         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10142         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10143         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10144         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10145         if (ent->model->brush.submodel && !prepass)
10146         {
10147                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10148                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10149         }
10150         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10151         {
10152                 if (ent->animcache_vertex3f && !r_framedata_failed)
10153                 {
10154                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10155                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10156                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10157                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10158                 }
10159                 else if (wanttangents)
10160                 {
10161                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10162                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10163                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10164                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10165                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10166                 }
10167                 else if (wantnormals)
10168                 {
10169                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10170                         rsurface.modelsvector3f = NULL;
10171                         rsurface.modeltvector3f = NULL;
10172                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10173                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10174                 }
10175                 else
10176                 {
10177                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10178                         rsurface.modelsvector3f = NULL;
10179                         rsurface.modeltvector3f = NULL;
10180                         rsurface.modelnormal3f = NULL;
10181                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10182                 }
10183                 rsurface.modelvertex3f_bufferobject = 0;
10184                 rsurface.modelvertex3f_bufferoffset = 0;
10185                 rsurface.modelsvector3f_bufferobject = 0;
10186                 rsurface.modelsvector3f_bufferoffset = 0;
10187                 rsurface.modeltvector3f_bufferobject = 0;
10188                 rsurface.modeltvector3f_bufferoffset = 0;
10189                 rsurface.modelnormal3f_bufferobject = 0;
10190                 rsurface.modelnormal3f_bufferoffset = 0;
10191                 rsurface.generatedvertex = true;
10192         }
10193         else
10194         {
10195                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10196                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
10197                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10198                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10199                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
10200                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10201                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10202                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
10203                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10204                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10205                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
10206                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10207                 rsurface.generatedvertex = false;
10208         }
10209         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10210         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
10211         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10212         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10213         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
10214         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10215         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10216         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
10217         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10218         rsurface.modelelement3i = model->surfmesh.data_element3i;
10219         rsurface.modelelement3s = model->surfmesh.data_element3s;
10220         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
10221         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
10222         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10223         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
10224         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
10225         rsurface.modelsurfaces = model->data_surfaces;
10226         rsurface.vertex3f  = rsurface.modelvertex3f;
10227         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
10228         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10229         rsurface.svector3f = rsurface.modelsvector3f;
10230         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
10231         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10232         rsurface.tvector3f = rsurface.modeltvector3f;
10233         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
10234         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10235         rsurface.normal3f  = rsurface.modelnormal3f;
10236         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
10237         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10238         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
10239 }
10240
10241 void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, int entflags, double shadertime, float r, float g, float b, float a, int numvertices, const float *vertex3f, const float *texcoord2f, const float *normal3f, const float *svector3f, const float *tvector3f, const float *color4f, int numtriangles, const int *element3i, const unsigned short *element3s, qboolean wantnormals, qboolean wanttangents)
10242 {
10243         rsurface.entity = r_refdef.scene.worldentity;
10244         rsurface.skeleton = NULL;
10245         rsurface.ent_skinnum = 0;
10246         rsurface.ent_qwskin = -1;
10247         rsurface.ent_shadertime = shadertime;
10248         rsurface.ent_flags = entflags;
10249         rsurface.modelnum_vertices = numvertices;
10250         rsurface.modelnum_triangles = numtriangles;
10251         if (rsurface.array_size < rsurface.modelnum_vertices)
10252                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
10253         rsurface.matrix = *matrix;
10254         rsurface.inversematrix = *inversematrix;
10255         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10256         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10257         R_EntityMatrix(&rsurface.matrix);
10258         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10259         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10260         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10261         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10262         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10263         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10264         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10265         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10266         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10267         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10268         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10269         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10270         VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
10271         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10272         rsurface.frameblend[0].lerp = 1;
10273         rsurface.ent_alttextures = false;
10274         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10275         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10276         if (wanttangents)
10277         {
10278                 rsurface.modelvertex3f = vertex3f;
10279                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
10280                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
10281                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10282         }
10283         else if (wantnormals)
10284         {
10285                 rsurface.modelvertex3f = vertex3f;
10286                 rsurface.modelsvector3f = NULL;
10287                 rsurface.modeltvector3f = NULL;
10288                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10289         }
10290         else
10291         {
10292                 rsurface.modelvertex3f = vertex3f;
10293                 rsurface.modelsvector3f = NULL;
10294                 rsurface.modeltvector3f = NULL;
10295                 rsurface.modelnormal3f = NULL;
10296         }
10297         rsurface.modelvertex3f_bufferobject = 0;
10298         rsurface.modelvertex3f_bufferoffset = 0;
10299         rsurface.modelsvector3f_bufferobject = 0;
10300         rsurface.modelsvector3f_bufferoffset = 0;
10301         rsurface.modeltvector3f_bufferobject = 0;
10302         rsurface.modeltvector3f_bufferoffset = 0;
10303         rsurface.modelnormal3f_bufferobject = 0;
10304         rsurface.modelnormal3f_bufferoffset = 0;
10305         rsurface.generatedvertex = true;
10306         rsurface.modellightmapcolor4f  = color4f;
10307         rsurface.modellightmapcolor4f_bufferobject = 0;
10308         rsurface.modellightmapcolor4f_bufferoffset = 0;
10309         rsurface.modeltexcoordtexture2f  = texcoord2f;
10310         rsurface.modeltexcoordtexture2f_bufferobject = 0;
10311         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10312         rsurface.modeltexcoordlightmap2f  = NULL;
10313         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
10314         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10315         rsurface.modelelement3i = element3i;
10316         rsurface.modelelement3s = element3s;
10317         rsurface.modelelement3i_bufferobject = 0;
10318         rsurface.modelelement3s_bufferobject = 0;
10319         rsurface.modellightmapoffsets = NULL;
10320         rsurface.modelsurfaces = NULL;
10321         rsurface.vertex3f  = rsurface.modelvertex3f;
10322         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
10323         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10324         rsurface.svector3f = rsurface.modelsvector3f;
10325         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
10326         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10327         rsurface.tvector3f = rsurface.modeltvector3f;
10328         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
10329         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10330         rsurface.normal3f  = rsurface.modelnormal3f;
10331         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
10332         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10333         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
10334
10335         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
10336         {
10337                 if ((wantnormals || wanttangents) && !normal3f)
10338                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10339                 if (wanttangents && !svector3f)
10340                         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);
10341         }
10342 }
10343
10344 float RSurf_FogPoint(const float *v)
10345 {
10346         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10347         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10348         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10349         float FogHeightFade = r_refdef.fogheightfade;
10350         float fogfrac;
10351         unsigned int fogmasktableindex;
10352         if (r_refdef.fogplaneviewabove)
10353                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10354         else
10355                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10356         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10357         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10358 }
10359
10360 float RSurf_FogVertex(const float *v)
10361 {
10362         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10363         float FogPlaneViewDist = rsurface.fogplaneviewdist;
10364         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10365         float FogHeightFade = rsurface.fogheightfade;
10366         float fogfrac;
10367         unsigned int fogmasktableindex;
10368         if (r_refdef.fogplaneviewabove)
10369                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10370         else
10371                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10372         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10373         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10374 }
10375
10376 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
10377 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
10378 {
10379         int deformindex;
10380         int texturesurfaceindex;
10381         int i, j;
10382         float amplitude;
10383         float animpos;
10384         float scale;
10385         const float *v1, *in_tc;
10386         float *out_tc;
10387         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
10388         float waveparms[4];
10389         q3shaderinfo_deform_t *deform;
10390         // 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
10391         if (rsurface.generatedvertex)
10392         {
10393                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
10394                         generatenormals = true;
10395                 for (i = 0;i < Q3MAXDEFORMS;i++)
10396                 {
10397                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
10398                         {
10399                                 generatetangents = true;
10400                                 generatenormals = true;
10401                         }
10402                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
10403                                 generatenormals = true;
10404                 }
10405                 if (generatenormals && !rsurface.modelnormal3f)
10406                 {
10407                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10408                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
10409                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
10410                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10411                 }
10412                 if (generatetangents && !rsurface.modelsvector3f)
10413                 {
10414                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10415                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
10416                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
10417                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10418                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
10419                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
10420                         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);
10421                 }
10422         }
10423         rsurface.vertex3f  = rsurface.modelvertex3f;
10424         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
10425         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10426         rsurface.svector3f = rsurface.modelsvector3f;
10427         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
10428         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10429         rsurface.tvector3f = rsurface.modeltvector3f;
10430         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
10431         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10432         rsurface.normal3f  = rsurface.modelnormal3f;
10433         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
10434         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10435         // if vertices are deformed (sprite flares and things in maps, possibly
10436         // water waves, bulges and other deformations), generate them into
10437         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
10438         // (may be static model data or generated data for an animated model, or
10439         //  the previous deform pass)
10440         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10441         {
10442                 switch (deform->deform)
10443                 {
10444                 default:
10445                 case Q3DEFORM_PROJECTIONSHADOW:
10446                 case Q3DEFORM_TEXT0:
10447                 case Q3DEFORM_TEXT1:
10448                 case Q3DEFORM_TEXT2:
10449                 case Q3DEFORM_TEXT3:
10450                 case Q3DEFORM_TEXT4:
10451                 case Q3DEFORM_TEXT5:
10452                 case Q3DEFORM_TEXT6:
10453                 case Q3DEFORM_TEXT7:
10454                 case Q3DEFORM_NONE:
10455                         break;
10456                 case Q3DEFORM_AUTOSPRITE:
10457                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10458                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10459                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10460                         VectorNormalize(newforward);
10461                         VectorNormalize(newright);
10462                         VectorNormalize(newup);
10463                         // make deformed versions of only the model vertices used by the specified surfaces
10464                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10465                         {
10466                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10467                                 // a single autosprite surface can contain multiple sprites...
10468                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
10469                                 {
10470                                         VectorClear(center);
10471                                         for (i = 0;i < 4;i++)
10472                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
10473                                         VectorScale(center, 0.25f, center);
10474                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
10475                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
10476                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
10477                                         for (i = 0;i < 4;i++)
10478                                         {
10479                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
10480                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
10481                                         }
10482                                 }
10483                                 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);
10484                                 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);
10485                         }
10486                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10487                         rsurface.vertex3f_bufferobject = 0;
10488                         rsurface.vertex3f_bufferoffset = 0;
10489                         rsurface.svector3f = rsurface.array_deformedsvector3f;
10490                         rsurface.svector3f_bufferobject = 0;
10491                         rsurface.svector3f_bufferoffset = 0;
10492                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
10493                         rsurface.tvector3f_bufferobject = 0;
10494                         rsurface.tvector3f_bufferoffset = 0;
10495                         rsurface.normal3f = rsurface.array_deformednormal3f;
10496                         rsurface.normal3f_bufferobject = 0;
10497                         rsurface.normal3f_bufferoffset = 0;
10498                         break;
10499                 case Q3DEFORM_AUTOSPRITE2:
10500                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10501                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10502                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10503                         VectorNormalize(newforward);
10504                         VectorNormalize(newright);
10505                         VectorNormalize(newup);
10506                         // make deformed versions of only the model vertices used by the specified surfaces
10507                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10508                         {
10509                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10510                                 const float *v1, *v2;
10511                                 vec3_t start, end;
10512                                 float f, l;
10513                                 struct
10514                                 {
10515                                         float length2;
10516                                         const float *v1;
10517                                         const float *v2;
10518                                 }
10519                                 shortest[2];
10520                                 memset(shortest, 0, sizeof(shortest));
10521                                 // a single autosprite surface can contain multiple sprites...
10522                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
10523                                 {
10524                                         VectorClear(center);
10525                                         for (i = 0;i < 4;i++)
10526                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
10527                                         VectorScale(center, 0.25f, center);
10528                                         // find the two shortest edges, then use them to define the
10529                                         // axis vectors for rotating around the central axis
10530                                         for (i = 0;i < 6;i++)
10531                                         {
10532                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
10533                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
10534 #if 0
10535                                                 Debug_PolygonBegin(NULL, 0);
10536                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
10537                                                 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);
10538                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
10539                                                 Debug_PolygonEnd();
10540 #endif
10541                                                 l = VectorDistance2(v1, v2);
10542                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
10543                                                 if (v1[2] != v2[2])
10544                                                         l += (1.0f / 1024.0f);
10545                                                 if (shortest[0].length2 > l || i == 0)
10546                                                 {
10547                                                         shortest[1] = shortest[0];
10548                                                         shortest[0].length2 = l;
10549                                                         shortest[0].v1 = v1;
10550                                                         shortest[0].v2 = v2;
10551                                                 }
10552                                                 else if (shortest[1].length2 > l || i == 1)
10553                                                 {
10554                                                         shortest[1].length2 = l;
10555                                                         shortest[1].v1 = v1;
10556                                                         shortest[1].v2 = v2;
10557                                                 }
10558                                         }
10559                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10560                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10561 #if 0
10562                                         Debug_PolygonBegin(NULL, 0);
10563                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
10564                                         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);
10565                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
10566                                         Debug_PolygonEnd();
10567 #endif
10568                                         // this calculates the right vector from the shortest edge
10569                                         // and the up vector from the edge midpoints
10570                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10571                                         VectorNormalize(right);
10572                                         VectorSubtract(end, start, up);
10573                                         VectorNormalize(up);
10574                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10575                                         VectorSubtract(rsurface.localvieworigin, center, forward);
10576                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10577                                         VectorNegate(forward, forward);
10578                                         VectorReflect(forward, 0, up, forward);
10579                                         VectorNormalize(forward);
10580                                         CrossProduct(up, forward, newright);
10581                                         VectorNormalize(newright);
10582 #if 0
10583                                         Debug_PolygonBegin(NULL, 0);
10584                                         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);
10585                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
10586                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
10587                                         Debug_PolygonEnd();
10588 #endif
10589 #if 0
10590                                         Debug_PolygonBegin(NULL, 0);
10591                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
10592                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
10593                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
10594                                         Debug_PolygonEnd();
10595 #endif
10596                                         // rotate the quad around the up axis vector, this is made
10597                                         // especially easy by the fact we know the quad is flat,
10598                                         // so we only have to subtract the center position and
10599                                         // measure distance along the right vector, and then
10600                                         // multiply that by the newright vector and add back the
10601                                         // center position
10602                                         // we also need to subtract the old position to undo the
10603                                         // displacement from the center, which we do with a
10604                                         // DotProduct, the subtraction/addition of center is also
10605                                         // optimized into DotProducts here
10606                                         l = DotProduct(right, center);
10607                                         for (i = 0;i < 4;i++)
10608                                         {
10609                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
10610                                                 f = DotProduct(right, v1) - l;
10611                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
10612                                         }
10613                                 }
10614                                 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);
10615                                 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);
10616                         }
10617                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10618                         rsurface.vertex3f_bufferobject = 0;
10619                         rsurface.vertex3f_bufferoffset = 0;
10620                         rsurface.svector3f = rsurface.array_deformedsvector3f;
10621                         rsurface.svector3f_bufferobject = 0;
10622                         rsurface.svector3f_bufferoffset = 0;
10623                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
10624                         rsurface.tvector3f_bufferobject = 0;
10625                         rsurface.tvector3f_bufferoffset = 0;
10626                         rsurface.normal3f = rsurface.array_deformednormal3f;
10627                         rsurface.normal3f_bufferobject = 0;
10628                         rsurface.normal3f_bufferoffset = 0;
10629                         break;
10630                 case Q3DEFORM_NORMAL:
10631                         // deform the normals to make reflections wavey
10632                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10633                         {
10634                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10635                                 for (j = 0;j < surface->num_vertices;j++)
10636                                 {
10637                                         float vertex[3];
10638                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
10639                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
10640                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
10641                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10642                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10643                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10644                                         VectorNormalize(normal);
10645                                 }
10646                                 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);
10647                         }
10648                         rsurface.svector3f = rsurface.array_deformedsvector3f;
10649                         rsurface.svector3f_bufferobject = 0;
10650                         rsurface.svector3f_bufferoffset = 0;
10651                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
10652                         rsurface.tvector3f_bufferobject = 0;
10653                         rsurface.tvector3f_bufferoffset = 0;
10654                         rsurface.normal3f = rsurface.array_deformednormal3f;
10655                         rsurface.normal3f_bufferobject = 0;
10656                         rsurface.normal3f_bufferoffset = 0;
10657                         break;
10658                 case Q3DEFORM_WAVE:
10659                         // deform vertex array to make wavey water and flags and such
10660                         waveparms[0] = deform->waveparms[0];
10661                         waveparms[1] = deform->waveparms[1];
10662                         waveparms[2] = deform->waveparms[2];
10663                         waveparms[3] = deform->waveparms[3];
10664                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10665                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10666                         // this is how a divisor of vertex influence on deformation
10667                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10668                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10669                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10670                         {
10671                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10672                                 for (j = 0;j < surface->num_vertices;j++)
10673                                 {
10674                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
10675                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
10676                                         // if the wavefunc depends on time, evaluate it per-vertex
10677                                         if (waveparms[3])
10678                                         {
10679                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
10680                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10681                                         }
10682                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
10683                                 }
10684                         }
10685                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10686                         rsurface.vertex3f_bufferobject = 0;
10687                         rsurface.vertex3f_bufferoffset = 0;
10688                         break;
10689                 case Q3DEFORM_BULGE:
10690                         // deform vertex array to make the surface have moving bulges
10691                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10692                         {
10693                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10694                                 for (j = 0;j < surface->num_vertices;j++)
10695                                 {
10696                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
10697                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
10698                                 }
10699                         }
10700                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10701                         rsurface.vertex3f_bufferobject = 0;
10702                         rsurface.vertex3f_bufferoffset = 0;
10703                         break;
10704                 case Q3DEFORM_MOVE:
10705                         // deform vertex array
10706                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10707                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10708                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10709                         VectorScale(deform->parms, scale, waveparms);
10710                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10711                         {
10712                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10713                                 for (j = 0;j < surface->num_vertices;j++)
10714                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
10715                         }
10716                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10717                         rsurface.vertex3f_bufferobject = 0;
10718                         rsurface.vertex3f_bufferoffset = 0;
10719                         break;
10720                 }
10721         }
10722         // generate texcoords based on the chosen texcoord source
10723         switch(rsurface.texture->tcgen.tcgen)
10724         {
10725         default:
10726         case Q3TCGEN_TEXTURE:
10727                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
10728                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
10729                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
10730                 break;
10731         case Q3TCGEN_LIGHTMAP:
10732                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
10733                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
10734                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
10735                 break;
10736         case Q3TCGEN_VECTOR:
10737                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10738                 {
10739                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10740                         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)
10741                         {
10742                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
10743                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
10744                         }
10745                 }
10746                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10747                 rsurface.texcoordtexture2f_bufferobject  = 0;
10748                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10749                 break;
10750         case Q3TCGEN_ENVIRONMENT:
10751                 // make environment reflections using a spheremap
10752                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10753                 {
10754                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10755                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
10756                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
10757                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
10758                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
10759                         {
10760                                 // identical to Q3A's method, but executed in worldspace so
10761                                 // carried models can be shiny too
10762
10763                                 float viewer[3], d, reflected[3], worldreflected[3];
10764
10765                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
10766                                 // VectorNormalize(viewer);
10767
10768                                 d = DotProduct(normal, viewer);
10769
10770                                 reflected[0] = normal[0]*2*d - viewer[0];
10771                                 reflected[1] = normal[1]*2*d - viewer[1];
10772                                 reflected[2] = normal[2]*2*d - viewer[2];
10773                                 // note: this is proportinal to viewer, so we can normalize later
10774
10775                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10776                                 VectorNormalize(worldreflected);
10777
10778                                 // note: this sphere map only uses world x and z!
10779                                 // so positive and negative y will LOOK THE SAME.
10780                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
10781                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
10782                         }
10783                 }
10784                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10785                 rsurface.texcoordtexture2f_bufferobject  = 0;
10786                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10787                 break;
10788         }
10789         // the only tcmod that needs software vertex processing is turbulent, so
10790         // check for it here and apply the changes if needed
10791         // and we only support that as the first one
10792         // (handling a mixture of turbulent and other tcmods would be problematic
10793         //  without punting it entirely to a software path)
10794         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10795         {
10796                 amplitude = rsurface.texture->tcmods[0].parms[1];
10797                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
10798                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10799                 {
10800                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10801                         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)
10802                         {
10803                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10804                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10805                         }
10806                 }
10807                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10808                 rsurface.texcoordtexture2f_bufferobject  = 0;
10809                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10810         }
10811         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
10812         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
10813         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10814         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
10815 }
10816
10817 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10818 {
10819         int i, j;
10820         const msurface_t *surface = texturesurfacelist[0];
10821         const msurface_t *surface2;
10822         int firstvertex;
10823         int endvertex;
10824         int numvertices;
10825         int numtriangles;
10826         // TODO: lock all array ranges before render, rather than on each surface
10827         if (texturenumsurfaces == 1)
10828                 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);
10829         else if (r_batchmode.integer == 2)
10830         {
10831                 #define MAXBATCHTRIANGLES 65536
10832                 int batchtriangles = 0;
10833                 static int batchelements[MAXBATCHTRIANGLES*3];
10834                 for (i = 0;i < texturenumsurfaces;i = j)
10835                 {
10836                         surface = texturesurfacelist[i];
10837                         j = i + 1;
10838                         if (surface->num_triangles > MAXBATCHTRIANGLES)
10839                         {
10840                                 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);
10841                                 continue;
10842                         }
10843                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10844                         batchtriangles = surface->num_triangles;
10845                         firstvertex = surface->num_firstvertex;
10846                         endvertex = surface->num_firstvertex + surface->num_vertices;
10847                         for (;j < texturenumsurfaces;j++)
10848                         {
10849                                 surface2 = texturesurfacelist[j];
10850                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10851                                         break;
10852                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10853                                 batchtriangles += surface2->num_triangles;
10854                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
10855                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10856                         }
10857                         surface2 = texturesurfacelist[j-1];
10858                         numvertices = endvertex - firstvertex;
10859                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10860                 }
10861         }
10862         else if (r_batchmode.integer == 1)
10863         {
10864                 for (i = 0;i < texturenumsurfaces;i = j)
10865                 {
10866                         surface = texturesurfacelist[i];
10867                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10868                                 if (texturesurfacelist[j] != surface2)
10869                                         break;
10870                         surface2 = texturesurfacelist[j-1];
10871                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10872                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10873                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10874                 }
10875         }
10876         else
10877         {
10878                 for (i = 0;i < texturenumsurfaces;i++)
10879                 {
10880                         surface = texturesurfacelist[i];
10881                         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);
10882                 }
10883         }
10884 }
10885
10886 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
10887 {
10888         switch(vid.renderpath)
10889         {
10890         case RENDERPATH_CGGL:
10891 #ifdef SUPPORTCG
10892                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
10893                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
10894 #endif
10895                 break;
10896         case RENDERPATH_GL20:
10897                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
10898                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
10899                 break;
10900         case RENDERPATH_GL13:
10901         case RENDERPATH_GL11:
10902                 R_Mesh_TexBind(0, surface->lightmaptexture);
10903                 break;
10904         }
10905 }
10906
10907 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
10908 {
10909         // pick the closest matching water plane and bind textures
10910         int planeindex, vertexindex;
10911         float d, bestd;
10912         vec3_t vert;
10913         const float *v;
10914         r_waterstate_waterplane_t *p, *bestp;
10915         bestd = 0;
10916         bestp = NULL;
10917         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10918         {
10919                 if(p->camera_entity != rsurface.texture->camera_entity)
10920                         continue;
10921                 d = 0;
10922                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
10923                 {
10924                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10925                         d += fabs(PlaneDiff(vert, &p->plane));
10926                 }
10927                 if (bestd > d || !bestp)
10928                 {
10929                         bestd = d;
10930                         bestp = p;
10931                 }
10932         }
10933         switch(vid.renderpath)
10934         {
10935         case RENDERPATH_CGGL:
10936 #ifdef SUPPORTCG
10937                 if (r_cg_permutation->fp_Texture_Refraction) {CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR}
10938                 else if (r_cg_permutation->fp_Texture_First) {CG_BindTexture(r_cg_permutation->fp_Texture_First, bestp ? bestp->texture_camera : r_texture_black);CHECKCGERROR}
10939                 if (r_cg_permutation->fp_Texture_Reflection) {CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR}
10940 #endif
10941                 break;
10942         case RENDERPATH_GL20:
10943                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10944                 else if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST, bestp ? bestp->texture_camera : r_texture_black);
10945                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10946                 break;
10947         case RENDERPATH_GL13:
10948         case RENDERPATH_GL11:
10949                 break;
10950         }
10951 }
10952
10953 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10954 {
10955         int i;
10956         const msurface_t *surface;
10957         if (r_waterstate.renderingscene)
10958                 return;
10959         for (i = 0;i < texturenumsurfaces;i++)
10960         {
10961                 surface = texturesurfacelist[i];
10962                 RSurf_BindLightmapForSurface(surface);
10963                 RSurf_BindReflectionForSurface(surface);
10964                 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);
10965         }
10966 }
10967
10968 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10969 {
10970         int i;
10971         int j;
10972         const msurface_t *surface = texturesurfacelist[0];
10973         const msurface_t *surface2;
10974         int firstvertex;
10975         int endvertex;
10976         int numvertices;
10977         int numtriangles;
10978         if (texturenumsurfaces == 1)
10979         {
10980                 RSurf_BindLightmapForSurface(surface);
10981                 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);
10982         }
10983         else if (r_batchmode.integer == 2)
10984         {
10985                 int batchtriangles = 0;
10986                 static int batchelements[MAXBATCHTRIANGLES*3];
10987                 for (i = 0;i < texturenumsurfaces;i = j)
10988                 {
10989                         surface = texturesurfacelist[i];
10990                         RSurf_BindLightmapForSurface(surface);
10991                         j = i + 1;
10992                         if (surface->num_triangles > MAXBATCHTRIANGLES)
10993                         {
10994                                 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);
10995                                 continue;
10996                         }
10997                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10998                         batchtriangles = surface->num_triangles;
10999                         firstvertex = surface->num_firstvertex;
11000                         endvertex = surface->num_firstvertex + surface->num_vertices;
11001                         for (;j < texturenumsurfaces;j++)
11002                         {
11003                                 surface2 = texturesurfacelist[j];
11004                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
11005                                         break;
11006                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
11007                                 batchtriangles += surface2->num_triangles;
11008                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
11009                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
11010                         }
11011                         surface2 = texturesurfacelist[j-1];
11012                         numvertices = endvertex - firstvertex;
11013                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
11014                 }
11015         }
11016         else if (r_batchmode.integer == 1)
11017         {
11018 #if 0
11019                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
11020                 for (i = 0;i < texturenumsurfaces;i = j)
11021                 {
11022                         surface = texturesurfacelist[i];
11023                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
11024                                 if (texturesurfacelist[j] != surface2)
11025                                         break;
11026                         Con_Printf(" %i", j - i);
11027                 }
11028                 Con_Printf("\n");
11029                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
11030 #endif
11031                 for (i = 0;i < texturenumsurfaces;i = j)
11032                 {
11033                         surface = texturesurfacelist[i];
11034                         RSurf_BindLightmapForSurface(surface);
11035                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
11036                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
11037                                         break;
11038 #if 0
11039                         Con_Printf(" %i", j - i);
11040 #endif
11041                         surface2 = texturesurfacelist[j-1];
11042                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
11043                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
11044                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
11045                 }
11046 #if 0
11047                 Con_Printf("\n");
11048 #endif
11049         }
11050         else
11051         {
11052                 for (i = 0;i < texturenumsurfaces;i++)
11053                 {
11054                         surface = texturesurfacelist[i];
11055                         RSurf_BindLightmapForSurface(surface);
11056                         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);
11057                 }
11058         }
11059 }
11060
11061 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11062 {
11063         int j;
11064         int texturesurfaceindex;
11065         if (r_showsurfaces.integer == 2)
11066         {
11067                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11068                 {
11069                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11070                         for (j = 0;j < surface->num_triangles;j++)
11071                         {
11072                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
11073                                 GL_Color(f, f, f, 1);
11074                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
11075                         }
11076                 }
11077         }
11078         else
11079         {
11080                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11081                 {
11082                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11083                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
11084                         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);
11085                         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);
11086                 }
11087         }
11088 }
11089
11090 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11091 {
11092         int texturesurfaceindex;
11093         int i;
11094         const float *v;
11095         float *c2;
11096         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11097         {
11098                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11099                 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)
11100                 {
11101                         c2[0] = 0.5;
11102                         c2[1] = 0.5;
11103                         c2[2] = 0.5;
11104                         c2[3] = 1;
11105                 }
11106         }
11107         rsurface.lightmapcolor4f = rsurface.array_color4f;
11108         rsurface.lightmapcolor4f_bufferobject = 0;
11109         rsurface.lightmapcolor4f_bufferoffset = 0;
11110 }
11111
11112 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11113 {
11114         int texturesurfaceindex;
11115         int i;
11116         float f;
11117         const float *v;
11118         const float *c;
11119         float *c2;
11120         if (rsurface.lightmapcolor4f)
11121         {
11122                 // generate color arrays for the surfaces in this list
11123                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11124                 {
11125                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11126                         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)
11127                         {
11128                                 f = RSurf_FogVertex(v);
11129                                 c2[0] = c[0] * f;
11130                                 c2[1] = c[1] * f;
11131                                 c2[2] = c[2] * f;
11132                                 c2[3] = c[3];
11133                         }
11134                 }
11135         }
11136         else
11137         {
11138                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11139                 {
11140                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11141                         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)
11142                         {
11143                                 f = RSurf_FogVertex(v);
11144                                 c2[0] = f;
11145                                 c2[1] = f;
11146                                 c2[2] = f;
11147                                 c2[3] = 1;
11148                         }
11149                 }
11150         }
11151         rsurface.lightmapcolor4f = rsurface.array_color4f;
11152         rsurface.lightmapcolor4f_bufferobject = 0;
11153         rsurface.lightmapcolor4f_bufferoffset = 0;
11154 }
11155
11156 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11157 {
11158         int texturesurfaceindex;
11159         int i;
11160         float f;
11161         const float *v;
11162         const float *c;
11163         float *c2;
11164         if (!rsurface.lightmapcolor4f)
11165                 return;
11166         // generate color arrays for the surfaces in this list
11167         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11168         {
11169                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11170                 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)
11171                 {
11172                         f = RSurf_FogVertex(v);
11173                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11174                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11175                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11176                         c2[3] = c[3];
11177                 }
11178         }
11179         rsurface.lightmapcolor4f = rsurface.array_color4f;
11180         rsurface.lightmapcolor4f_bufferobject = 0;
11181         rsurface.lightmapcolor4f_bufferoffset = 0;
11182 }
11183
11184 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
11185 {
11186         int texturesurfaceindex;
11187         int i;
11188         const float *c;
11189         float *c2;
11190         if (!rsurface.lightmapcolor4f)
11191                 return;
11192         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11193         {
11194                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11195                 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)
11196                 {
11197                         c2[0] = c[0] * r;
11198                         c2[1] = c[1] * g;
11199                         c2[2] = c[2] * b;
11200                         c2[3] = c[3] * a;
11201                 }
11202         }
11203         rsurface.lightmapcolor4f = rsurface.array_color4f;
11204         rsurface.lightmapcolor4f_bufferobject = 0;
11205         rsurface.lightmapcolor4f_bufferoffset = 0;
11206 }
11207
11208 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11209 {
11210         int texturesurfaceindex;
11211         int i;
11212         const float *c;
11213         float *c2;
11214         if (!rsurface.lightmapcolor4f)
11215                 return;
11216         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11217         {
11218                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11219                 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)
11220                 {
11221                         c2[0] = c[0] + r_refdef.scene.ambient;
11222                         c2[1] = c[1] + r_refdef.scene.ambient;
11223                         c2[2] = c[2] + r_refdef.scene.ambient;
11224                         c2[3] = c[3];
11225                 }
11226         }
11227         rsurface.lightmapcolor4f = rsurface.array_color4f;
11228         rsurface.lightmapcolor4f_bufferobject = 0;
11229         rsurface.lightmapcolor4f_bufferoffset = 0;
11230 }
11231
11232 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11233 {
11234         // TODO: optimize
11235         rsurface.lightmapcolor4f = NULL;
11236         rsurface.lightmapcolor4f_bufferobject = 0;
11237         rsurface.lightmapcolor4f_bufferoffset = 0;
11238         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
11239         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
11240         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11241         GL_Color(r, g, b, a);
11242         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
11243 }
11244
11245 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11246 {
11247         // TODO: optimize applyfog && applycolor case
11248         // just apply fog if necessary, and tint the fog color array if necessary
11249         rsurface.lightmapcolor4f = NULL;
11250         rsurface.lightmapcolor4f_bufferobject = 0;
11251         rsurface.lightmapcolor4f_bufferoffset = 0;
11252         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
11253         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
11254         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11255         GL_Color(r, g, b, a);
11256         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11257 }
11258
11259 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11260 {
11261         int texturesurfaceindex;
11262         int i;
11263         float *c;
11264         // TODO: optimize
11265         if (texturesurfacelist[0]->lightmapinfo)
11266         {
11267                 // generate color arrays for the surfaces in this list
11268                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11269                 {
11270                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11271                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
11272                         {
11273                                 if (surface->lightmapinfo->samples)
11274                                 {
11275                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
11276                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
11277                                         VectorScale(lm, scale, c);
11278                                         if (surface->lightmapinfo->styles[1] != 255)
11279                                         {
11280                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11281                                                 lm += size3;
11282                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
11283                                                 VectorMA(c, scale, lm, c);
11284                                                 if (surface->lightmapinfo->styles[2] != 255)
11285                                                 {
11286                                                         lm += size3;
11287                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
11288                                                         VectorMA(c, scale, lm, c);
11289                                                         if (surface->lightmapinfo->styles[3] != 255)
11290                                                         {
11291                                                                 lm += size3;
11292                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
11293                                                                 VectorMA(c, scale, lm, c);
11294                                                         }
11295                                                 }
11296                                         }
11297                                 }
11298                                 else
11299                                         VectorClear(c);
11300                                 c[3] = 1;
11301                         }
11302                 }
11303                 rsurface.lightmapcolor4f = rsurface.array_color4f;
11304                 rsurface.lightmapcolor4f_bufferobject = 0;
11305                 rsurface.lightmapcolor4f_bufferoffset = 0;
11306         }
11307         else
11308         {
11309                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
11310                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
11311                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11312         }
11313         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
11314         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
11315         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11316         GL_Color(r, g, b, a);
11317         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11318 }
11319
11320 static void RSurf_DrawBatch_GL11_ApplyFakeLight(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11321 {
11322         int texturesurfaceindex;
11323         int i;
11324         float f;
11325         const float *v;
11326         const float *n;
11327         float *c;
11328         //vec3_t eyedir;
11329
11330         // fake shading
11331         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11332         {
11333                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11334                 int numverts = surface->num_vertices;
11335                 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
11336                 n = rsurface.normal3f + 3 * surface->num_firstvertex;
11337                 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
11338                 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
11339                 {
11340                         f = -DotProduct(r_refdef.view.forward, n);
11341                         f = max(0, f);
11342                         f = f * 0.85 + 0.15; // work around so stuff won't get black
11343                         f *= r_refdef.lightmapintensity;
11344                         Vector4Set(c, f, f, f, 1);
11345                 }
11346         }
11347
11348         rsurface.lightmapcolor4f = rsurface.array_color4f;
11349         rsurface.lightmapcolor4f_bufferobject = 0;
11350         rsurface.lightmapcolor4f_bufferoffset = 0;
11351 }
11352
11353 static void RSurf_DrawBatch_GL11_FakeLight(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11354 {
11355         RSurf_DrawBatch_GL11_ApplyFakeLight(texturenumsurfaces, texturesurfacelist);
11356         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
11357         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
11358         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11359         GL_Color(r, g, b, a);
11360         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11361 }
11362
11363 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
11364 {
11365         int texturesurfaceindex;
11366         int i;
11367         float f;
11368         float alpha;
11369         const float *v;
11370         const float *n;
11371         float *c;
11372         vec3_t ambientcolor;
11373         vec3_t diffusecolor;
11374         vec3_t lightdir;
11375         // TODO: optimize
11376         // model lighting
11377         VectorCopy(rsurface.modellight_lightdir, lightdir);
11378         f = 0.5f * r_refdef.lightmapintensity;
11379         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
11380         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
11381         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
11382         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
11383         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
11384         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
11385         alpha = *a;
11386         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
11387         {
11388                 // generate color arrays for the surfaces in this list
11389                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11390                 {
11391                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11392                         int numverts = surface->num_vertices;
11393                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
11394                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
11395                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
11396                         // q3-style directional shading
11397                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
11398                         {
11399                                 if ((f = DotProduct(n, lightdir)) > 0)
11400                                         VectorMA(ambientcolor, f, diffusecolor, c);
11401                                 else
11402                                         VectorCopy(ambientcolor, c);
11403                                 c[3] = alpha;
11404                         }
11405                 }
11406                 *r = 1;
11407                 *g = 1;
11408                 *b = 1;
11409                 *a = 1;
11410                 rsurface.lightmapcolor4f = rsurface.array_color4f;
11411                 rsurface.lightmapcolor4f_bufferobject = 0;
11412                 rsurface.lightmapcolor4f_bufferoffset = 0;
11413                 *applycolor = false;
11414         }
11415         else
11416         {
11417                 *r = ambientcolor[0];
11418                 *g = ambientcolor[1];
11419                 *b = ambientcolor[2];
11420                 rsurface.lightmapcolor4f = NULL;
11421                 rsurface.lightmapcolor4f_bufferobject = 0;
11422                 rsurface.lightmapcolor4f_bufferoffset = 0;
11423         }
11424 }
11425
11426 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11427 {
11428         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
11429         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
11430         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
11431         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11432         GL_Color(r, g, b, a);
11433         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11434 }
11435
11436 void RSurf_SetupDepthAndCulling(void)
11437 {
11438         // submodels are biased to avoid z-fighting with world surfaces that they
11439         // may be exactly overlapping (avoids z-fighting artifacts on certain
11440         // doors and things in Quake maps)
11441         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
11442         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
11443         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
11444         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11445 }
11446
11447 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11448 {
11449         // transparent sky would be ridiculous
11450         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11451                 return;
11452         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11453         skyrenderlater = true;
11454         RSurf_SetupDepthAndCulling();
11455         GL_DepthMask(true);
11456         // LordHavoc: HalfLife maps have freaky skypolys so don't use
11457         // skymasking on them, and Quake3 never did sky masking (unlike
11458         // software Quake and software Quake2), so disable the sky masking
11459         // in Quake3 maps as it causes problems with q3map2 sky tricks,
11460         // and skymasking also looks very bad when noclipping outside the
11461         // level, so don't use it then either.
11462         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
11463         {
11464                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
11465                 R_Mesh_ColorPointer(NULL, 0, 0);
11466                 R_Mesh_ResetTextureState();
11467                 if (skyrendermasked)
11468                 {
11469                         R_SetupShader_DepthOrShadow();
11470                         // depth-only (masking)
11471                         GL_ColorMask(0,0,0,0);
11472                         // just to make sure that braindead drivers don't draw
11473                         // anything despite that colormask...
11474                         GL_BlendFunc(GL_ZERO, GL_ONE);
11475                 }
11476                 else
11477                 {
11478                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11479                         // fog sky
11480                         GL_BlendFunc(GL_ONE, GL_ZERO);
11481                 }
11482                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11483                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11484                 if (skyrendermasked)
11485                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11486         }
11487         R_Mesh_ResetTextureState();
11488         GL_Color(1, 1, 1, 1);
11489 }
11490
11491 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
11492 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
11493 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11494 {
11495         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
11496                 return;
11497         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
11498         if (prepass)
11499         {
11500                 // render screenspace normalmap to texture
11501                 GL_DepthMask(true);
11502                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
11503                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11504         }
11505         else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
11506         {
11507                 // render water or distortion background, then blend surface on top
11508                 GL_DepthMask(true);
11509                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
11510                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
11511                 GL_DepthMask(false);
11512                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
11513                 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11514                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
11515                 else
11516                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11517         }
11518         else
11519         {
11520                 // render surface normally
11521                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
11522                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
11523                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
11524                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
11525                 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11526                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
11527                 else
11528                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11529         }
11530 }
11531
11532 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11533 {
11534         // OpenGL 1.3 path - anything not completely ancient
11535         int texturesurfaceindex;
11536         qboolean applycolor;
11537         qboolean applyfog;
11538         int layerindex;
11539         const texturelayer_t *layer;
11540         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11541
11542         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11543         {
11544                 vec4_t layercolor;
11545                 int layertexrgbscale;
11546                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11547                 {
11548                         if (layerindex == 0)
11549                                 GL_AlphaTest(true);
11550                         else
11551                         {
11552                                 GL_AlphaTest(false);
11553                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
11554                         }
11555                 }
11556                 GL_DepthMask(layer->depthmask && writedepth);
11557                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11558                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
11559                 {
11560                         layertexrgbscale = 4;
11561                         VectorScale(layer->color, 0.25f, layercolor);
11562                 }
11563                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
11564                 {
11565                         layertexrgbscale = 2;
11566                         VectorScale(layer->color, 0.5f, layercolor);
11567                 }
11568                 else
11569                 {
11570                         layertexrgbscale = 1;
11571                         VectorScale(layer->color, 1.0f, layercolor);
11572                 }
11573                 layercolor[3] = layer->color[3];
11574                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
11575                 R_Mesh_ColorPointer(NULL, 0, 0);
11576                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11577                 switch (layer->type)
11578                 {
11579                 case TEXTURELAYERTYPE_LITTEXTURE:
11580                         // single-pass lightmapped texture with 2x rgbscale
11581                         R_Mesh_TexBind(0, r_texture_white);
11582                         R_Mesh_TexMatrix(0, NULL);
11583                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11584                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
11585                         R_Mesh_TexBind(1, layer->texture);
11586                         R_Mesh_TexMatrix(1, &layer->texmatrix);
11587                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11588                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11589                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11590                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11591                         else if (FAKELIGHT_ENABLED)
11592                                 RSurf_DrawBatch_GL11_FakeLight(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11593                         else if (rsurface.uselightmaptexture)
11594                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11595                         else
11596                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11597                         break;
11598                 case TEXTURELAYERTYPE_TEXTURE:
11599                         // singletexture unlit texture with transparency support
11600                         R_Mesh_TexBind(0, layer->texture);
11601                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11602                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11603                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11604                         R_Mesh_TexBind(1, 0);
11605                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
11606                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11607                         break;
11608                 case TEXTURELAYERTYPE_FOG:
11609                         // singletexture fogging
11610                         if (layer->texture)
11611                         {
11612                                 R_Mesh_TexBind(0, layer->texture);
11613                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11614                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11615                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11616                         }
11617                         else
11618                         {
11619                                 R_Mesh_TexBind(0, 0);
11620                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
11621                         }
11622                         R_Mesh_TexBind(1, 0);
11623                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
11624                         // generate a color array for the fog pass
11625                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
11626                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11627                         {
11628                                 int i;
11629                                 float f;
11630                                 const float *v;
11631                                 float *c;
11632                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11633                                 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)
11634                                 {
11635                                         f = 1 - RSurf_FogVertex(v);
11636                                         c[0] = layercolor[0];
11637                                         c[1] = layercolor[1];
11638                                         c[2] = layercolor[2];
11639                                         c[3] = f * layercolor[3];
11640                                 }
11641                         }
11642                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11643                         break;
11644                 default:
11645                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11646                 }
11647         }
11648         CHECKGLERROR
11649         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11650         {
11651                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11652                 GL_AlphaTest(false);
11653         }
11654 }
11655
11656 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11657 {
11658         // OpenGL 1.1 - crusty old voodoo path
11659         int texturesurfaceindex;
11660         qboolean applyfog;
11661         int layerindex;
11662         const texturelayer_t *layer;
11663         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11664
11665         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11666         {
11667                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11668                 {
11669                         if (layerindex == 0)
11670                                 GL_AlphaTest(true);
11671                         else
11672                         {
11673                                 GL_AlphaTest(false);
11674                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
11675                         }
11676                 }
11677                 GL_DepthMask(layer->depthmask && writedepth);
11678                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11679                 R_Mesh_ColorPointer(NULL, 0, 0);
11680                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11681                 switch (layer->type)
11682                 {
11683                 case TEXTURELAYERTYPE_LITTEXTURE:
11684                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
11685                         {
11686                                 // two-pass lit texture with 2x rgbscale
11687                                 // first the lightmap pass
11688                                 R_Mesh_TexBind(0, r_texture_white);
11689                                 R_Mesh_TexMatrix(0, NULL);
11690                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11691                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
11692                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11693                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11694                                 else if (FAKELIGHT_ENABLED)
11695                                         RSurf_DrawBatch_GL11_FakeLight(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11696                                 else if (rsurface.uselightmaptexture)
11697                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11698                                 else
11699                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11700                                 // then apply the texture to it
11701                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
11702                                 R_Mesh_TexBind(0, layer->texture);
11703                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11704                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11705                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11706                                 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);
11707                         }
11708                         else
11709                         {
11710                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
11711                                 R_Mesh_TexBind(0, layer->texture);
11712                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11713                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11714                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11715                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11716                                         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);
11717                                 else
11718                                         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);
11719                         }
11720                         break;
11721                 case TEXTURELAYERTYPE_TEXTURE:
11722                         // singletexture unlit texture with transparency support
11723                         R_Mesh_TexBind(0, layer->texture);
11724                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11725                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11726                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11727                         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);
11728                         break;
11729                 case TEXTURELAYERTYPE_FOG:
11730                         // singletexture fogging
11731                         if (layer->texture)
11732                         {
11733                                 R_Mesh_TexBind(0, layer->texture);
11734                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11735                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11736                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11737                         }
11738                         else
11739                         {
11740                                 R_Mesh_TexBind(0, 0);
11741                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
11742                         }
11743                         // generate a color array for the fog pass
11744                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
11745                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11746                         {
11747                                 int i;
11748                                 float f;
11749                                 const float *v;
11750                                 float *c;
11751                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11752                                 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)
11753                                 {
11754                                         f = 1 - RSurf_FogVertex(v);
11755                                         c[0] = layer->color[0];
11756                                         c[1] = layer->color[1];
11757                                         c[2] = layer->color[2];
11758                                         c[3] = f * layer->color[3];
11759                                 }
11760                         }
11761                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11762                         break;
11763                 default:
11764                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11765                 }
11766         }
11767         CHECKGLERROR
11768         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11769         {
11770                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11771                 GL_AlphaTest(false);
11772         }
11773 }
11774
11775 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11776 {
11777         float c[4];
11778
11779         GL_AlphaTest(false);
11780         R_Mesh_ColorPointer(NULL, 0, 0);
11781         R_Mesh_ResetTextureState();
11782         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11783
11784         if(rsurface.texture && rsurface.texture->currentskinframe)
11785         {
11786                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11787                 c[3] *= rsurface.texture->currentalpha;
11788         }
11789         else
11790         {
11791                 c[0] = 1;
11792                 c[1] = 0;
11793                 c[2] = 1;
11794                 c[3] = 1;
11795         }
11796
11797         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11798         {
11799                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11800                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11801                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11802         }
11803
11804         // brighten it up (as texture value 127 means "unlit")
11805         c[0] *= 2 * r_refdef.view.colorscale;
11806         c[1] *= 2 * r_refdef.view.colorscale;
11807         c[2] *= 2 * r_refdef.view.colorscale;
11808
11809         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11810                 c[3] *= r_wateralpha.value;
11811
11812         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11813         {
11814                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11815                 GL_DepthMask(false);
11816         }
11817         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11818         {
11819                 GL_BlendFunc(GL_ONE, GL_ONE);
11820                 GL_DepthMask(false);
11821         }
11822         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11823         {
11824                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11825                 GL_DepthMask(false);
11826         }
11827         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11828         {
11829                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11830                 GL_DepthMask(false);
11831         }
11832         else
11833         {
11834                 GL_BlendFunc(GL_ONE, GL_ZERO);
11835                 GL_DepthMask(writedepth);
11836         }
11837
11838         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11839         {
11840                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11841
11842                 rsurface.lightmapcolor4f = NULL;
11843                 rsurface.lightmapcolor4f_bufferobject = 0;
11844                 rsurface.lightmapcolor4f_bufferoffset = 0;
11845         }
11846         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11847         {
11848                 qboolean applycolor = true;
11849                 float one = 1.0;
11850
11851                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11852
11853                 r_refdef.lightmapintensity = 1;
11854                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
11855                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11856         }
11857         else if (FAKELIGHT_ENABLED)
11858         {
11859                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11860
11861                 r_refdef.lightmapintensity = r_fakelight_intensity.value;
11862                 RSurf_DrawBatch_GL11_ApplyFakeLight(texturenumsurfaces, texturesurfacelist);
11863                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11864         }
11865         else
11866         {
11867                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11868
11869                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
11870                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
11871                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11872         }
11873
11874         if(!rsurface.lightmapcolor4f)
11875                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
11876
11877         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
11878         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
11879         if(r_refdef.fogenabled)
11880                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
11881
11882         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11883         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11884 }
11885
11886 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11887 {
11888         CHECKGLERROR
11889         RSurf_SetupDepthAndCulling();
11890         if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11891         {
11892                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11893                 return;
11894         }
11895         switch (vid.renderpath)
11896         {
11897         case RENDERPATH_GL20:
11898         case RENDERPATH_CGGL:
11899                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11900                 break;
11901         case RENDERPATH_GL13:
11902                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11903                 break;
11904         case RENDERPATH_GL11:
11905                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11906                 break;
11907         }
11908         CHECKGLERROR
11909 }
11910
11911 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11912 {
11913         CHECKGLERROR
11914         RSurf_SetupDepthAndCulling();
11915         if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11916         {
11917                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11918                 return;
11919         }
11920         switch (vid.renderpath)
11921         {
11922         case RENDERPATH_GL20:
11923         case RENDERPATH_CGGL:
11924                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11925                 break;
11926         case RENDERPATH_GL13:
11927                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11928                 break;
11929         case RENDERPATH_GL11:
11930                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11931                 break;
11932         }
11933         CHECKGLERROR
11934 }
11935
11936 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11937 {
11938         int i, j;
11939         int texturenumsurfaces, endsurface;
11940         texture_t *texture;
11941         const msurface_t *surface;
11942 #define MAXBATCH_TRANSPARENTSURFACES 256
11943         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
11944
11945         // if the model is static it doesn't matter what value we give for
11946         // wantnormals and wanttangents, so this logic uses only rules applicable
11947         // to a model, knowing that they are meaningless otherwise
11948         if (ent == r_refdef.scene.worldentity)
11949                 RSurf_ActiveWorldEntity();
11950         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11951                 RSurf_ActiveModelEntity(ent, false, false, false);
11952         else
11953         {
11954                 switch (vid.renderpath)
11955                 {
11956                 case RENDERPATH_GL20:
11957                 case RENDERPATH_CGGL:
11958                         RSurf_ActiveModelEntity(ent, true, true, false);
11959                         break;
11960                 case RENDERPATH_GL13:
11961                 case RENDERPATH_GL11:
11962                         RSurf_ActiveModelEntity(ent, true, false, false);
11963                         break;
11964                 }
11965         }
11966
11967         if (r_transparentdepthmasking.integer)
11968         {
11969                 qboolean setup = false;
11970                 for (i = 0;i < numsurfaces;i = j)
11971                 {
11972                         j = i + 1;
11973                         surface = rsurface.modelsurfaces + surfacelist[i];
11974                         texture = surface->texture;
11975                         rsurface.texture = R_GetCurrentTexture(texture);
11976                         // scan ahead until we find a different texture
11977                         endsurface = min(i + 1024, numsurfaces);
11978                         texturenumsurfaces = 0;
11979                         texturesurfacelist[texturenumsurfaces++] = surface;
11980                         if(FAKELIGHT_ENABLED)
11981                         {
11982                                 rsurface.uselightmaptexture = false;
11983                                 for (;j < endsurface;j++)
11984                                 {
11985                                         surface = rsurface.modelsurfaces + surfacelist[j];
11986                                         if (texture != surface->texture)
11987                                                 break;
11988                                         texturesurfacelist[texturenumsurfaces++] = surface;
11989                                 }
11990                         }
11991                         else
11992                         {
11993                                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11994                                 for (;j < endsurface;j++)
11995                                 {
11996                                         surface = rsurface.modelsurfaces + surfacelist[j];
11997                                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11998                                                 break;
11999                                         texturesurfacelist[texturenumsurfaces++] = surface;
12000                                 }
12001                         }
12002                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12003                                 continue;
12004                         // render the range of surfaces as depth
12005                         if (!setup)
12006                         {
12007                                 setup = true;
12008                                 GL_ColorMask(0,0,0,0);
12009                                 GL_Color(1,1,1,1);
12010                                 GL_DepthTest(true);
12011                                 GL_BlendFunc(GL_ONE, GL_ZERO);
12012                                 GL_DepthMask(true);
12013                                 GL_AlphaTest(false);
12014                                 R_Mesh_ColorPointer(NULL, 0, 0);
12015                                 R_Mesh_ResetTextureState();
12016                                 R_SetupShader_DepthOrShadow();
12017                         }
12018                         RSurf_SetupDepthAndCulling();
12019                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12020                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
12021                 }
12022                 if (setup)
12023                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12024         }
12025
12026         for (i = 0;i < numsurfaces;i = j)
12027         {
12028                 j = i + 1;
12029                 surface = rsurface.modelsurfaces + surfacelist[i];
12030                 texture = surface->texture;
12031                 rsurface.texture = R_GetCurrentTexture(texture);
12032                 // scan ahead until we find a different texture
12033                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12034                 texturenumsurfaces = 0;
12035                 texturesurfacelist[texturenumsurfaces++] = surface;
12036                 if(FAKELIGHT_ENABLED)
12037                 {
12038                         rsurface.uselightmaptexture = false;
12039                         for (;j < endsurface;j++)
12040                         {
12041                                 surface = rsurface.modelsurfaces + surfacelist[j];
12042                                 if (texture != surface->texture)
12043                                         break;
12044                                 texturesurfacelist[texturenumsurfaces++] = surface;
12045                         }
12046                 }
12047                 else
12048                 {
12049                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12050                         for (;j < endsurface;j++)
12051                         {
12052                                 surface = rsurface.modelsurfaces + surfacelist[j];
12053                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
12054                                         break;
12055                                 texturesurfacelist[texturenumsurfaces++] = surface;
12056                         }
12057                 }
12058                 // render the range of surfaces
12059                 if (ent == r_refdef.scene.worldentity)
12060                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12061                 else
12062                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12063         }
12064         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12065         GL_AlphaTest(false);
12066 }
12067
12068 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12069 {
12070         // transparent surfaces get pushed off into the transparent queue
12071         int surfacelistindex;
12072         const msurface_t *surface;
12073         vec3_t tempcenter, center;
12074         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12075         {
12076                 surface = texturesurfacelist[surfacelistindex];
12077                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12078                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12079                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12080                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12081                 if (queueentity->transparent_offset) // transparent offset
12082                 {
12083                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12084                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12085                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12086                 }
12087                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12088         }
12089 }
12090
12091 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12092 {
12093         const entity_render_t *queueentity = r_refdef.scene.worldentity;
12094         CHECKGLERROR
12095         if (depthonly)
12096         {
12097                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12098                         return;
12099                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12100                         return;
12101                 RSurf_SetupDepthAndCulling();
12102                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12103                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
12104         }
12105         else if (prepass)
12106         {
12107                 if (!rsurface.texture->currentnumlayers)
12108                         return;
12109                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12110                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12111                 else
12112                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12113         }
12114         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
12115         {
12116                 RSurf_SetupDepthAndCulling();
12117                 GL_AlphaTest(false);
12118                 R_Mesh_ColorPointer(NULL, 0, 0);
12119                 R_Mesh_ResetTextureState();
12120                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12121                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12122                 GL_DepthMask(true);
12123                 GL_BlendFunc(GL_ONE, GL_ZERO);
12124                 GL_Color(0, 0, 0, 1);
12125                 GL_DepthTest(writedepth);
12126                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
12127         }
12128         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
12129         {
12130                 RSurf_SetupDepthAndCulling();
12131                 GL_AlphaTest(false);
12132                 R_Mesh_ColorPointer(NULL, 0, 0);
12133                 R_Mesh_ResetTextureState();
12134                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12135                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12136                 GL_DepthMask(true);
12137                 GL_BlendFunc(GL_ONE, GL_ZERO);
12138                 GL_DepthTest(true);
12139                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
12140         }
12141         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
12142                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12143         else if (!rsurface.texture->currentnumlayers)
12144                 return;
12145         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12146         {
12147                 // in the deferred case, transparent surfaces were queued during prepass
12148                 if (!r_shadow_usingdeferredprepass)
12149                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12150         }
12151         else
12152         {
12153                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12154                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12155         }
12156         CHECKGLERROR
12157 }
12158
12159 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12160 {
12161         int i, j;
12162         texture_t *texture;
12163         // break the surface list down into batches by texture and use of lightmapping
12164         for (i = 0;i < numsurfaces;i = j)
12165         {
12166                 j = i + 1;
12167                 // texture is the base texture pointer, rsurface.texture is the
12168                 // current frame/skin the texture is directing us to use (for example
12169                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12170                 // use skin 1 instead)
12171                 texture = surfacelist[i]->texture;
12172                 rsurface.texture = R_GetCurrentTexture(texture);
12173                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12174                 {
12175                         // if this texture is not the kind we want, skip ahead to the next one
12176                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12177                                 ;
12178                         continue;
12179                 }
12180                 if(FAKELIGHT_ENABLED || depthonly || prepass)
12181                 {
12182                         rsurface.uselightmaptexture = false;
12183                         // simply scan ahead until we find a different texture or lightmap state
12184                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12185                                 ;
12186                 }
12187                 else
12188                 {
12189                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12190                         // simply scan ahead until we find a different texture or lightmap state
12191                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
12192                                 ;
12193                 }
12194                 // render the range of surfaces
12195                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12196         }
12197 }
12198
12199 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12200 {
12201         CHECKGLERROR
12202         if (depthonly)
12203         {
12204                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12205                         return;
12206                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12207                         return;
12208                 RSurf_SetupDepthAndCulling();
12209                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12210                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
12211         }
12212         else if (prepass)
12213         {
12214                 if (!rsurface.texture->currentnumlayers)
12215                         return;
12216                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12217                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12218                 else
12219                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12220         }
12221         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
12222         {
12223                 RSurf_SetupDepthAndCulling();
12224                 GL_AlphaTest(false);
12225                 R_Mesh_ColorPointer(NULL, 0, 0);
12226                 R_Mesh_ResetTextureState();
12227                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12228                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12229                 GL_DepthMask(true);
12230                 GL_BlendFunc(GL_ONE, GL_ZERO);
12231                 GL_Color(0, 0, 0, 1);
12232                 GL_DepthTest(writedepth);
12233                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
12234         }
12235         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12236         {
12237                 RSurf_SetupDepthAndCulling();
12238                 GL_AlphaTest(false);
12239                 R_Mesh_ColorPointer(NULL, 0, 0);
12240                 R_Mesh_ResetTextureState();
12241                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12242                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12243                 GL_DepthMask(true);
12244                 GL_BlendFunc(GL_ONE, GL_ZERO);
12245                 GL_DepthTest(true);
12246                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
12247         }
12248         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
12249                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12250         else if (!rsurface.texture->currentnumlayers)
12251                 return;
12252         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12253         {
12254                 // in the deferred case, transparent surfaces were queued during prepass
12255                 if (!r_shadow_usingdeferredprepass)
12256                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12257         }
12258         else
12259         {
12260                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12261                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12262         }
12263         CHECKGLERROR
12264 }
12265
12266 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12267 {
12268         int i, j;
12269         texture_t *texture;
12270         // break the surface list down into batches by texture and use of lightmapping
12271         for (i = 0;i < numsurfaces;i = j)
12272         {
12273                 j = i + 1;
12274                 // texture is the base texture pointer, rsurface.texture is the
12275                 // current frame/skin the texture is directing us to use (for example
12276                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12277                 // use skin 1 instead)
12278                 texture = surfacelist[i]->texture;
12279                 rsurface.texture = R_GetCurrentTexture(texture);
12280                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12281                 {
12282                         // if this texture is not the kind we want, skip ahead to the next one
12283                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12284                                 ;
12285                         continue;
12286                 }
12287                 if(FAKELIGHT_ENABLED || depthonly || prepass)
12288                 {
12289                         rsurface.uselightmaptexture = false;
12290                         // simply scan ahead until we find a different texture or lightmap state
12291                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12292                                 ;
12293                 }
12294                 else
12295                 {
12296                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12297                         // simply scan ahead until we find a different texture or lightmap state
12298                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
12299                                 ;
12300                 }
12301                 // render the range of surfaces
12302                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12303         }
12304 }
12305
12306 float locboxvertex3f[6*4*3] =
12307 {
12308         1,0,1, 1,0,0, 1,1,0, 1,1,1,
12309         0,1,1, 0,1,0, 0,0,0, 0,0,1,
12310         1,1,1, 1,1,0, 0,1,0, 0,1,1,
12311         0,0,1, 0,0,0, 1,0,0, 1,0,1,
12312         0,0,1, 1,0,1, 1,1,1, 0,1,1,
12313         1,0,0, 0,0,0, 0,1,0, 1,1,0
12314 };
12315
12316 unsigned short locboxelements[6*2*3] =
12317 {
12318          0, 1, 2, 0, 2, 3,
12319          4, 5, 6, 4, 6, 7,
12320          8, 9,10, 8,10,11,
12321         12,13,14, 12,14,15,
12322         16,17,18, 16,18,19,
12323         20,21,22, 20,22,23
12324 };
12325
12326 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12327 {
12328         int i, j;
12329         cl_locnode_t *loc = (cl_locnode_t *)ent;
12330         vec3_t mins, size;
12331         float vertex3f[6*4*3];
12332         CHECKGLERROR
12333         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12334         GL_DepthMask(false);
12335         GL_DepthRange(0, 1);
12336         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12337         GL_DepthTest(true);
12338         GL_CullFace(GL_NONE);
12339         R_EntityMatrix(&identitymatrix);
12340
12341         R_Mesh_VertexPointer(vertex3f, 0, 0);
12342         R_Mesh_ColorPointer(NULL, 0, 0);
12343         R_Mesh_ResetTextureState();
12344         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12345
12346         i = surfacelist[0];
12347         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12348                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12349                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12350                         surfacelist[0] < 0 ? 0.5f : 0.125f);
12351
12352         if (VectorCompare(loc->mins, loc->maxs))
12353         {
12354                 VectorSet(size, 2, 2, 2);
12355                 VectorMA(loc->mins, -0.5f, size, mins);
12356         }
12357         else
12358         {
12359                 VectorCopy(loc->mins, mins);
12360                 VectorSubtract(loc->maxs, loc->mins, size);
12361         }
12362
12363         for (i = 0;i < 6*4*3;)
12364                 for (j = 0;j < 3;j++, i++)
12365                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
12366
12367         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
12368 }
12369
12370 void R_DrawLocs(void)
12371 {
12372         int index;
12373         cl_locnode_t *loc, *nearestloc;
12374         vec3_t center;
12375         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
12376         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
12377         {
12378                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
12379                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
12380         }
12381 }
12382
12383 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
12384 {
12385         if (decalsystem->decals)
12386                 Mem_Free(decalsystem->decals);
12387         memset(decalsystem, 0, sizeof(*decalsystem));
12388 }
12389
12390 static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float *v0, const float *v1, const float *v2, const float *t0, const float *t1, const float *t2, const float *c0, const float *c1, const float *c2, int triangleindex, int surfaceindex, int decalsequence)
12391 {
12392         tridecal_t *decal;
12393         tridecal_t *decals;
12394         int i;
12395
12396         // expand or initialize the system
12397         if (decalsystem->maxdecals <= decalsystem->numdecals)
12398         {
12399                 decalsystem_t old = *decalsystem;
12400                 qboolean useshortelements;
12401                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
12402                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
12403                 decalsystem->decals = Mem_Alloc(cls.levelmempool, decalsystem->maxdecals * (sizeof(tridecal_t) + sizeof(float[3][3]) + sizeof(float[3][2]) + sizeof(float[3][4]) + sizeof(int[3]) + (useshortelements ? sizeof(unsigned short[3]) : 0)));
12404                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
12405                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
12406                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
12407                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
12408                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
12409                 if (decalsystem->numdecals)
12410                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
12411                 if (old.decals)
12412                         Mem_Free(old.decals);
12413                 for (i = 0;i < decalsystem->maxdecals*3;i++)
12414                         decalsystem->element3i[i] = i;
12415                 if (useshortelements)
12416                         for (i = 0;i < decalsystem->maxdecals*3;i++)
12417                                 decalsystem->element3s[i] = i;
12418         }
12419
12420         // grab a decal and search for another free slot for the next one
12421         decals = decalsystem->decals;
12422         decal = decalsystem->decals + (i = decalsystem->freedecal++);
12423         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
12424                 ;
12425         decalsystem->freedecal = i;
12426         if (decalsystem->numdecals <= i)
12427                 decalsystem->numdecals = i + 1;
12428
12429         // initialize the decal
12430         decal->lived = 0;
12431         decal->triangleindex = triangleindex;
12432         decal->surfaceindex = surfaceindex;
12433         decal->decalsequence = decalsequence;
12434         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
12435         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
12436         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
12437         decal->color4ub[0][3] = 255;
12438         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
12439         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
12440         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
12441         decal->color4ub[1][3] = 255;
12442         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
12443         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
12444         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
12445         decal->color4ub[2][3] = 255;
12446         decal->vertex3f[0][0] = v0[0];
12447         decal->vertex3f[0][1] = v0[1];
12448         decal->vertex3f[0][2] = v0[2];
12449         decal->vertex3f[1][0] = v1[0];
12450         decal->vertex3f[1][1] = v1[1];
12451         decal->vertex3f[1][2] = v1[2];
12452         decal->vertex3f[2][0] = v2[0];
12453         decal->vertex3f[2][1] = v2[1];
12454         decal->vertex3f[2][2] = v2[2];
12455         decal->texcoord2f[0][0] = t0[0];
12456         decal->texcoord2f[0][1] = t0[1];
12457         decal->texcoord2f[1][0] = t1[0];
12458         decal->texcoord2f[1][1] = t1[1];
12459         decal->texcoord2f[2][0] = t2[0];
12460         decal->texcoord2f[2][1] = t2[1];
12461 }
12462
12463 extern cvar_t cl_decals_bias;
12464 extern cvar_t cl_decals_models;
12465 extern cvar_t cl_decals_newsystem_intensitymultiplier;
12466 // baseparms, parms, temps
12467 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
12468 {
12469         int cornerindex;
12470         int index;
12471         float v[9][3];
12472         const float *vertex3f;
12473         int numpoints;
12474         float points[2][9][3];
12475         float temp[3];
12476         float tc[9][2];
12477         float f;
12478         float c[9][4];
12479         const int *e;
12480
12481         e = rsurface.modelelement3i + 3*triangleindex;
12482
12483         vertex3f = rsurface.modelvertex3f;
12484
12485         for (cornerindex = 0;cornerindex < 3;cornerindex++)
12486         {
12487                 index = 3*e[cornerindex];
12488                 VectorCopy(vertex3f + index, v[cornerindex]);
12489         }
12490         // cull backfaces
12491         //TriangleNormal(v[0], v[1], v[2], normal);
12492         //if (DotProduct(normal, localnormal) < 0.0f)
12493         //      continue;
12494         // clip by each of the box planes formed from the projection matrix
12495         // if anything survives, we emit the decal
12496         numpoints = PolygonF_Clip(3        , v[0]        , planes[0][0], planes[0][1], planes[0][2], planes[0][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
12497         if (numpoints < 3)
12498                 return;
12499         numpoints = PolygonF_Clip(numpoints, points[1][0], planes[1][0], planes[1][1], planes[1][2], planes[1][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
12500         if (numpoints < 3)
12501                 return;
12502         numpoints = PolygonF_Clip(numpoints, points[0][0], planes[2][0], planes[2][1], planes[2][2], planes[2][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
12503         if (numpoints < 3)
12504                 return;
12505         numpoints = PolygonF_Clip(numpoints, points[1][0], planes[3][0], planes[3][1], planes[3][2], planes[3][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
12506         if (numpoints < 3)
12507                 return;
12508         numpoints = PolygonF_Clip(numpoints, points[0][0], planes[4][0], planes[4][1], planes[4][2], planes[4][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
12509         if (numpoints < 3)
12510                 return;
12511         numpoints = PolygonF_Clip(numpoints, points[1][0], planes[5][0], planes[5][1], planes[5][2], planes[5][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), v[0]);
12512         if (numpoints < 3)
12513                 return;
12514         // some part of the triangle survived, so we have to accept it...
12515         if (dynamic)
12516         {
12517                 // dynamic always uses the original triangle
12518                 numpoints = 3;
12519                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
12520                 {
12521                         index = 3*e[cornerindex];
12522                         VectorCopy(vertex3f + index, v[cornerindex]);
12523                 }
12524         }
12525         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
12526         {
12527                 // convert vertex positions to texcoords
12528                 Matrix4x4_Transform(projection, v[cornerindex], temp);
12529                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
12530                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
12531                 // calculate distance fade from the projection origin
12532                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
12533                 f = bound(0.0f, f, 1.0f);
12534                 c[cornerindex][0] = r * f;
12535                 c[cornerindex][1] = g * f;
12536                 c[cornerindex][2] = b * f;
12537                 c[cornerindex][3] = 1.0f;
12538                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
12539         }
12540         if (dynamic)
12541                 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex, surfaceindex, decalsequence);
12542         else
12543                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
12544                         R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[cornerindex+1], v[cornerindex+2], tc[0], tc[cornerindex+1], tc[cornerindex+2], c[0], c[cornerindex+1], c[cornerindex+2], -1, surfaceindex, decalsequence);
12545 }
12546 static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
12547 {
12548         matrix4x4_t projection;
12549         decalsystem_t *decalsystem;
12550         qboolean dynamic;
12551         dp_model_t *model;
12552         const msurface_t *surface;
12553         const msurface_t *surfaces;
12554         const int *surfacelist;
12555         const texture_t *texture;
12556         int numtriangles;
12557         int numsurfacelist;
12558         int surfacelistindex;
12559         int surfaceindex;
12560         int triangleindex;
12561         float localorigin[3];
12562         float localnormal[3];
12563         float localmins[3];
12564         float localmaxs[3];
12565         float localsize;
12566         //float normal[3];
12567         float planes[6][4];
12568         float angles[3];
12569         bih_t *bih;
12570         int bih_triangles_count;
12571         int bih_triangles[256];
12572         int bih_surfaces[256];
12573
12574         decalsystem = &ent->decalsystem;
12575         model = ent->model;
12576         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
12577         {
12578                 R_DecalSystem_Reset(&ent->decalsystem);
12579                 return;
12580         }
12581
12582         if (!model->brush.data_nodes && !cl_decals_models.integer)
12583         {
12584                 if (decalsystem->model)
12585                         R_DecalSystem_Reset(decalsystem);
12586                 return;
12587         }
12588
12589         if (decalsystem->model != model)
12590                 R_DecalSystem_Reset(decalsystem);
12591         decalsystem->model = model;
12592
12593         RSurf_ActiveModelEntity(ent, false, false, false);
12594
12595         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
12596         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
12597         VectorNormalize(localnormal);
12598         localsize = worldsize*rsurface.inversematrixscale;
12599         localmins[0] = localorigin[0] - localsize;
12600         localmins[1] = localorigin[1] - localsize;
12601         localmins[2] = localorigin[2] - localsize;
12602         localmaxs[0] = localorigin[0] + localsize;
12603         localmaxs[1] = localorigin[1] + localsize;
12604         localmaxs[2] = localorigin[2] + localsize;
12605
12606         //VectorCopy(localnormal, planes[4]);
12607         //VectorVectors(planes[4], planes[2], planes[0]);
12608         AnglesFromVectors(angles, localnormal, NULL, false);
12609         AngleVectors(angles, planes[0], planes[2], planes[4]);
12610         VectorNegate(planes[0], planes[1]);
12611         VectorNegate(planes[2], planes[3]);
12612         VectorNegate(planes[4], planes[5]);
12613         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
12614         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
12615         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
12616         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
12617         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
12618         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
12619
12620 #if 1
12621 // works
12622 {
12623         matrix4x4_t forwardprojection;
12624         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
12625         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
12626 }
12627 #else
12628 // broken
12629 {
12630         float projectionvector[4][3];
12631         VectorScale(planes[0], ilocalsize, projectionvector[0]);
12632         VectorScale(planes[2], ilocalsize, projectionvector[1]);
12633         VectorScale(planes[4], ilocalsize, projectionvector[2]);
12634         projectionvector[0][0] = planes[0][0] * ilocalsize;
12635         projectionvector[0][1] = planes[1][0] * ilocalsize;
12636         projectionvector[0][2] = planes[2][0] * ilocalsize;
12637         projectionvector[1][0] = planes[0][1] * ilocalsize;
12638         projectionvector[1][1] = planes[1][1] * ilocalsize;
12639         projectionvector[1][2] = planes[2][1] * ilocalsize;
12640         projectionvector[2][0] = planes[0][2] * ilocalsize;
12641         projectionvector[2][1] = planes[1][2] * ilocalsize;
12642         projectionvector[2][2] = planes[2][2] * ilocalsize;
12643         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
12644         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
12645         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
12646         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
12647 }
12648 #endif
12649
12650         dynamic = model->surfmesh.isanimated;
12651         numsurfacelist = model->nummodelsurfaces;
12652         surfacelist = model->sortedmodelsurfaces;
12653         surfaces = model->data_surfaces;
12654
12655         bih = NULL;
12656         bih_triangles_count = -1;
12657         if(!dynamic)
12658         {
12659                 if(model->render_bih.numleafs)
12660                         bih = &model->render_bih;
12661                 else if(model->collision_bih.numleafs)
12662                         bih = &model->collision_bih;
12663         }
12664         if(bih)
12665                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
12666         if(bih_triangles_count == 0)
12667                 return;
12668         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
12669                 return;
12670         if(bih_triangles_count > 0)
12671         {
12672                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
12673                 {
12674                         surfaceindex = bih_surfaces[triangleindex];
12675                         surface = surfaces + surfaceindex;
12676                         texture = surface->texture;
12677                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12678                                 continue;
12679                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12680                                 continue;
12681                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
12682                 }
12683         }
12684         else
12685         {
12686                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
12687                 {
12688                         surfaceindex = surfacelist[surfacelistindex];
12689                         surface = surfaces + surfaceindex;
12690                         // check cull box first because it rejects more than any other check
12691                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
12692                                 continue;
12693                         // skip transparent surfaces
12694                         texture = surface->texture;
12695                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12696                                 continue;
12697                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12698                                 continue;
12699                         numtriangles = surface->num_triangles;
12700                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
12701                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
12702                 }
12703         }
12704 }
12705
12706 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12707 static void R_DecalSystem_ApplySplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
12708 {
12709         int renderentityindex;
12710         float worldmins[3];
12711         float worldmaxs[3];
12712         entity_render_t *ent;
12713
12714         if (!cl_decals_newsystem.integer)
12715                 return;
12716
12717         worldmins[0] = worldorigin[0] - worldsize;
12718         worldmins[1] = worldorigin[1] - worldsize;
12719         worldmins[2] = worldorigin[2] - worldsize;
12720         worldmaxs[0] = worldorigin[0] + worldsize;
12721         worldmaxs[1] = worldorigin[1] + worldsize;
12722         worldmaxs[2] = worldorigin[2] + worldsize;
12723
12724         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12725
12726         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12727         {
12728                 ent = r_refdef.scene.entities[renderentityindex];
12729                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12730                         continue;
12731
12732                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12733         }
12734 }
12735
12736 typedef struct r_decalsystem_splatqueue_s
12737 {
12738         vec3_t worldorigin;
12739         vec3_t worldnormal;
12740         float color[4];
12741         float tcrange[4];
12742         float worldsize;
12743         int decalsequence;
12744 }
12745 r_decalsystem_splatqueue_t;
12746
12747 int r_decalsystem_numqueued = 0;
12748 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12749
12750 void R_DecalSystem_SplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize)
12751 {
12752         r_decalsystem_splatqueue_t *queue;
12753
12754         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12755                 return;
12756
12757         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12758         VectorCopy(worldorigin, queue->worldorigin);
12759         VectorCopy(worldnormal, queue->worldnormal);
12760         Vector4Set(queue->color, r, g, b, a);
12761         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12762         queue->worldsize = worldsize;
12763         queue->decalsequence = cl.decalsequence++;
12764 }
12765
12766 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12767 {
12768         int i;
12769         r_decalsystem_splatqueue_t *queue;
12770
12771         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12772                 R_DecalSystem_ApplySplatEntities(queue->worldorigin, queue->worldnormal, queue->color[0], queue->color[1], queue->color[2], queue->color[3], queue->tcrange[0], queue->tcrange[1], queue->tcrange[2], queue->tcrange[3], queue->worldsize, queue->decalsequence);
12773         r_decalsystem_numqueued = 0;
12774 }
12775
12776 extern cvar_t cl_decals_max;
12777 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12778 {
12779         int i;
12780         decalsystem_t *decalsystem = &ent->decalsystem;
12781         int numdecals;
12782         int killsequence;
12783         tridecal_t *decal;
12784         float frametime;
12785         float lifetime;
12786
12787         if (!decalsystem->numdecals)
12788                 return;
12789
12790         if (r_showsurfaces.integer)
12791                 return;
12792
12793         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12794         {
12795                 R_DecalSystem_Reset(decalsystem);
12796                 return;
12797         }
12798
12799         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12800         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12801
12802         if (decalsystem->lastupdatetime)
12803                 frametime = (cl.time - decalsystem->lastupdatetime);
12804         else
12805                 frametime = 0;
12806         decalsystem->lastupdatetime = cl.time;
12807         decal = decalsystem->decals;
12808         numdecals = decalsystem->numdecals;
12809
12810         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12811         {
12812                 if (decal->color4ub[0][3])
12813                 {
12814                         decal->lived += frametime;
12815                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12816                         {
12817                                 memset(decal, 0, sizeof(*decal));
12818                                 if (decalsystem->freedecal > i)
12819                                         decalsystem->freedecal = i;
12820                         }
12821                 }
12822         }
12823         decal = decalsystem->decals;
12824         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
12825                 numdecals--;
12826
12827         // collapse the array by shuffling the tail decals into the gaps
12828         for (;;)
12829         {
12830                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
12831                         decalsystem->freedecal++;
12832                 if (decalsystem->freedecal == numdecals)
12833                         break;
12834                 decal[decalsystem->freedecal] = decal[--numdecals];
12835         }
12836
12837         decalsystem->numdecals = numdecals;
12838
12839         if (numdecals <= 0)
12840         {
12841                 // if there are no decals left, reset decalsystem
12842                 R_DecalSystem_Reset(decalsystem);
12843         }
12844 }
12845
12846 extern skinframe_t *decalskinframe;
12847 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12848 {
12849         int i;
12850         decalsystem_t *decalsystem = &ent->decalsystem;
12851         int numdecals;
12852         tridecal_t *decal;
12853         float faderate;
12854         float alpha;
12855         float *v3f;
12856         float *c4f;
12857         float *t2f;
12858         const int *e;
12859         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12860         int numtris = 0;
12861
12862         numdecals = decalsystem->numdecals;
12863         if (!numdecals)
12864                 return;
12865
12866         if (r_showsurfaces.integer)
12867                 return;
12868
12869         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12870         {
12871                 R_DecalSystem_Reset(decalsystem);
12872                 return;
12873         }
12874
12875         // if the model is static it doesn't matter what value we give for
12876         // wantnormals and wanttangents, so this logic uses only rules applicable
12877         // to a model, knowing that they are meaningless otherwise
12878         if (ent == r_refdef.scene.worldentity)
12879                 RSurf_ActiveWorldEntity();
12880         else
12881                 RSurf_ActiveModelEntity(ent, false, false, false);
12882
12883         decalsystem->lastupdatetime = cl.time;
12884         decal = decalsystem->decals;
12885
12886         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12887
12888         // update vertex positions for animated models
12889         v3f = decalsystem->vertex3f;
12890         c4f = decalsystem->color4f;
12891         t2f = decalsystem->texcoord2f;
12892         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12893         {
12894                 if (!decal->color4ub[0][3])
12895                         continue;
12896
12897                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12898                         continue;
12899
12900                 // update color values for fading decals
12901                 if (decal->lived >= cl_decals_time.value)
12902                 {
12903                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12904                         alpha *= (1.0f/255.0f);
12905                 }
12906                 else
12907                         alpha = 1.0f/255.0f;
12908
12909                 c4f[ 0] = decal->color4ub[0][0] * alpha;
12910                 c4f[ 1] = decal->color4ub[0][1] * alpha;
12911                 c4f[ 2] = decal->color4ub[0][2] * alpha;
12912                 c4f[ 3] = 1;
12913                 c4f[ 4] = decal->color4ub[1][0] * alpha;
12914                 c4f[ 5] = decal->color4ub[1][1] * alpha;
12915                 c4f[ 6] = decal->color4ub[1][2] * alpha;
12916                 c4f[ 7] = 1;
12917                 c4f[ 8] = decal->color4ub[2][0] * alpha;
12918                 c4f[ 9] = decal->color4ub[2][1] * alpha;
12919                 c4f[10] = decal->color4ub[2][2] * alpha;
12920                 c4f[11] = 1;
12921
12922                 t2f[0] = decal->texcoord2f[0][0];
12923                 t2f[1] = decal->texcoord2f[0][1];
12924                 t2f[2] = decal->texcoord2f[1][0];
12925                 t2f[3] = decal->texcoord2f[1][1];
12926                 t2f[4] = decal->texcoord2f[2][0];
12927                 t2f[5] = decal->texcoord2f[2][1];
12928
12929                 // update vertex positions for animated models
12930                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
12931                 {
12932                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12933                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
12934                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
12935                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
12936                 }
12937                 else
12938                 {
12939                         VectorCopy(decal->vertex3f[0], v3f);
12940                         VectorCopy(decal->vertex3f[1], v3f + 3);
12941                         VectorCopy(decal->vertex3f[2], v3f + 6);
12942                 }
12943
12944                 if (r_refdef.fogenabled)
12945                 {
12946                         alpha = RSurf_FogVertex(v3f);
12947                         VectorScale(c4f, alpha, c4f);
12948                         alpha = RSurf_FogVertex(v3f + 3);
12949                         VectorScale(c4f + 4, alpha, c4f + 4);
12950                         alpha = RSurf_FogVertex(v3f + 6);
12951                         VectorScale(c4f + 8, alpha, c4f + 8);
12952                 }
12953
12954                 v3f += 9;
12955                 c4f += 12;
12956                 t2f += 6;
12957                 numtris++;
12958         }
12959
12960         if (numtris > 0)
12961         {
12962                 r_refdef.stats.drawndecals += numtris;
12963
12964                 // now render the decals all at once
12965                 // (this assumes they all use one particle font texture!)
12966                 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
12967                 R_Mesh_ResetTextureState();
12968                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
12969                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
12970                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
12971                 GL_DepthMask(false);
12972                 GL_DepthRange(0, 1);
12973                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12974                 GL_DepthTest(true);
12975                 GL_CullFace(GL_NONE);
12976                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12977                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
12978                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
12979         }
12980 }
12981
12982 static void R_DrawModelDecals(void)
12983 {
12984         int i, numdecals;
12985
12986         // fade faster when there are too many decals
12987         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12988         for (i = 0;i < r_refdef.scene.numentities;i++)
12989                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12990
12991         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12992         for (i = 0;i < r_refdef.scene.numentities;i++)
12993                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12994                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12995
12996         R_DecalSystem_ApplySplatEntitiesQueue();
12997
12998         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12999         for (i = 0;i < r_refdef.scene.numentities;i++)
13000                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13001
13002         r_refdef.stats.totaldecals += numdecals;
13003
13004         if (r_showsurfaces.integer)
13005                 return;
13006
13007         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13008
13009         for (i = 0;i < r_refdef.scene.numentities;i++)
13010         {
13011                 if (!r_refdef.viewcache.entityvisible[i])
13012                         continue;
13013                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13014                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13015         }
13016 }
13017
13018 extern cvar_t mod_collision_bih;
13019 void R_DrawDebugModel(void)
13020 {
13021         entity_render_t *ent = rsurface.entity;
13022         int i, j, k, l, flagsmask;
13023         const msurface_t *surface;
13024         dp_model_t *model = ent->model;
13025         vec3_t v;
13026
13027         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13028
13029         R_Mesh_ColorPointer(NULL, 0, 0);
13030         R_Mesh_ResetTextureState();
13031         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13032         GL_DepthRange(0, 1);
13033         GL_DepthTest(!r_showdisabledepthtest.integer);
13034         GL_DepthMask(false);
13035         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13036
13037         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13038         {
13039                 int triangleindex;
13040                 int bihleafindex;
13041                 qboolean cullbox = ent == r_refdef.scene.worldentity;
13042                 const q3mbrush_t *brush;
13043                 const bih_t *bih = &model->collision_bih;
13044                 const bih_leaf_t *bihleaf;
13045                 float vertex3f[3][3];
13046                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13047                 cullbox = false;
13048                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13049                 {
13050                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13051                                 continue;
13052                         switch (bihleaf->type)
13053                         {
13054                         case BIH_BRUSH:
13055                                 brush = model->brush.data_brushes + bihleaf->itemindex;
13056                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
13057                                 {
13058                                         R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
13059                                         GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
13060                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
13061                                 }
13062                                 break;
13063                         case BIH_COLLISIONTRIANGLE:
13064                                 triangleindex = bihleaf->itemindex;
13065                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13066                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13067                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13068                                 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
13069                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
13070                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
13071                                 break;
13072                         case BIH_RENDERTRIANGLE:
13073                                 triangleindex = bihleaf->itemindex;
13074                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13075                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13076                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13077                                 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
13078                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
13079                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
13080                                 break;
13081                         }
13082                 }
13083         }
13084
13085         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13086
13087         if (r_showtris.integer || r_shownormals.integer)
13088         {
13089                 if (r_showdisabledepthtest.integer)
13090                 {
13091                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13092                         GL_DepthMask(false);
13093                 }
13094                 else
13095                 {
13096                         GL_BlendFunc(GL_ONE, GL_ZERO);
13097                         GL_DepthMask(true);
13098                 }
13099                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13100                 {
13101                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13102                                 continue;
13103                         rsurface.texture = R_GetCurrentTexture(surface->texture);
13104                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13105                         {
13106                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
13107                                 if (r_showtris.value > 0)
13108                                 {
13109                                         if (!rsurface.texture->currentlayers->depthmask)
13110                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13111                                         else if (ent == r_refdef.scene.worldentity)
13112                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13113                                         else
13114                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13115                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
13116                                         R_Mesh_ColorPointer(NULL, 0, 0);
13117                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
13118                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13119                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
13120                                         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);
13121                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13122                                         CHECKGLERROR
13123                                 }
13124                                 if (r_shownormals.value < 0)
13125                                 {
13126                                         qglBegin(GL_LINES);
13127                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13128                                         {
13129                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
13130                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13131                                                 qglVertex3f(v[0], v[1], v[2]);
13132                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
13133                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13134                                                 qglVertex3f(v[0], v[1], v[2]);
13135                                         }
13136                                         qglEnd();
13137                                         CHECKGLERROR
13138                                 }
13139                                 if (r_shownormals.value > 0)
13140                                 {
13141                                         qglBegin(GL_LINES);
13142                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13143                                         {
13144                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
13145                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13146                                                 qglVertex3f(v[0], v[1], v[2]);
13147                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
13148                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13149                                                 qglVertex3f(v[0], v[1], v[2]);
13150                                         }
13151                                         qglEnd();
13152                                         CHECKGLERROR
13153                                         qglBegin(GL_LINES);
13154                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13155                                         {
13156                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
13157                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13158                                                 qglVertex3f(v[0], v[1], v[2]);
13159                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
13160                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13161                                                 qglVertex3f(v[0], v[1], v[2]);
13162                                         }
13163                                         qglEnd();
13164                                         CHECKGLERROR
13165                                         qglBegin(GL_LINES);
13166                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13167                                         {
13168                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
13169                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13170                                                 qglVertex3f(v[0], v[1], v[2]);
13171                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
13172                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13173                                                 qglVertex3f(v[0], v[1], v[2]);
13174                                         }
13175                                         qglEnd();
13176                                         CHECKGLERROR
13177                                 }
13178                         }
13179                 }
13180                 rsurface.texture = NULL;
13181         }
13182 }
13183
13184 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13185 int r_maxsurfacelist = 0;
13186 const msurface_t **r_surfacelist = NULL;
13187 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13188 {
13189         int i, j, endj, flagsmask;
13190         dp_model_t *model = r_refdef.scene.worldmodel;
13191         msurface_t *surfaces;
13192         unsigned char *update;
13193         int numsurfacelist = 0;
13194         if (model == NULL)
13195                 return;
13196
13197         if (r_maxsurfacelist < model->num_surfaces)
13198         {
13199                 r_maxsurfacelist = model->num_surfaces;
13200                 if (r_surfacelist)
13201                         Mem_Free((msurface_t**)r_surfacelist);
13202                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13203         }
13204
13205         RSurf_ActiveWorldEntity();
13206
13207         surfaces = model->data_surfaces;
13208         update = model->brushq1.lightmapupdateflags;
13209
13210         // update light styles on this submodel
13211         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13212         {
13213                 model_brush_lightstyleinfo_t *style;
13214                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13215                 {
13216                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13217                         {
13218                                 int *list = style->surfacelist;
13219                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13220                                 for (j = 0;j < style->numsurfaces;j++)
13221                                         update[list[j]] = true;
13222                         }
13223                 }
13224         }
13225
13226         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13227
13228         if (debug)
13229         {
13230                 R_DrawDebugModel();
13231                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13232                 return;
13233         }
13234
13235         rsurface.uselightmaptexture = false;
13236         rsurface.texture = NULL;
13237         rsurface.rtlight = NULL;
13238         numsurfacelist = 0;
13239         // add visible surfaces to draw list
13240         for (i = 0;i < model->nummodelsurfaces;i++)
13241         {
13242                 j = model->sortedmodelsurfaces[i];
13243                 if (r_refdef.viewcache.world_surfacevisible[j])
13244                         r_surfacelist[numsurfacelist++] = surfaces + j;
13245         }
13246         // update lightmaps if needed
13247         if (model->brushq1.firstrender)
13248         {
13249                 model->brushq1.firstrender = false;
13250                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13251                         if (update[j])
13252                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13253         }
13254         else if (update)
13255         {
13256                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13257                         if (r_refdef.viewcache.world_surfacevisible[j])
13258                                 if (update[j])
13259                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13260         }
13261         // don't do anything if there were no surfaces
13262         if (!numsurfacelist)
13263         {
13264                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13265                 return;
13266         }
13267         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13268         GL_AlphaTest(false);
13269
13270         // add to stats if desired
13271         if (r_speeds.integer && !skysurfaces && !depthonly)
13272         {
13273                 r_refdef.stats.world_surfaces += numsurfacelist;
13274                 for (j = 0;j < numsurfacelist;j++)
13275                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13276         }
13277
13278         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13279 }
13280
13281 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13282 {
13283         int i, j, endj, flagsmask;
13284         dp_model_t *model = ent->model;
13285         msurface_t *surfaces;
13286         unsigned char *update;
13287         int numsurfacelist = 0;
13288         if (model == NULL)
13289                 return;
13290
13291         if (r_maxsurfacelist < model->num_surfaces)
13292         {
13293                 r_maxsurfacelist = model->num_surfaces;
13294                 if (r_surfacelist)
13295                         Mem_Free((msurface_t **)r_surfacelist);
13296                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13297         }
13298
13299         // if the model is static it doesn't matter what value we give for
13300         // wantnormals and wanttangents, so this logic uses only rules applicable
13301         // to a model, knowing that they are meaningless otherwise
13302         if (ent == r_refdef.scene.worldentity)
13303                 RSurf_ActiveWorldEntity();
13304         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13305                 RSurf_ActiveModelEntity(ent, false, false, false);
13306         else if (prepass)
13307                 RSurf_ActiveModelEntity(ent, true, true, true);
13308         else if (depthonly)
13309         {
13310                 switch (vid.renderpath)
13311                 {
13312                 case RENDERPATH_GL20:
13313                 case RENDERPATH_CGGL:
13314                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
13315                         break;
13316                 case RENDERPATH_GL13:
13317                 case RENDERPATH_GL11:
13318                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
13319                         break;
13320                 }
13321         }
13322         else
13323         {
13324                 switch (vid.renderpath)
13325                 {
13326                 case RENDERPATH_GL20:
13327                 case RENDERPATH_CGGL:
13328                         RSurf_ActiveModelEntity(ent, true, true, false);
13329                         break;
13330                 case RENDERPATH_GL13:
13331                 case RENDERPATH_GL11:
13332                         RSurf_ActiveModelEntity(ent, true, false, false);
13333                         break;
13334                 }
13335         }
13336
13337         surfaces = model->data_surfaces;
13338         update = model->brushq1.lightmapupdateflags;
13339
13340         // update light styles
13341         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13342         {
13343                 model_brush_lightstyleinfo_t *style;
13344                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13345                 {
13346                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13347                         {
13348                                 int *list = style->surfacelist;
13349                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13350                                 for (j = 0;j < style->numsurfaces;j++)
13351                                         update[list[j]] = true;
13352                         }
13353                 }
13354         }
13355
13356         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13357
13358         if (debug)
13359         {
13360                 R_DrawDebugModel();
13361                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13362                 return;
13363         }
13364
13365         rsurface.uselightmaptexture = false;
13366         rsurface.texture = NULL;
13367         rsurface.rtlight = NULL;
13368         numsurfacelist = 0;
13369         // add visible surfaces to draw list
13370         for (i = 0;i < model->nummodelsurfaces;i++)
13371                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
13372         // don't do anything if there were no surfaces
13373         if (!numsurfacelist)
13374         {
13375                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13376                 return;
13377         }
13378         // update lightmaps if needed
13379         if (update)
13380         {
13381                 int updated = 0;
13382                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13383                 {
13384                         if (update[j])
13385                         {
13386                                 updated++;
13387                                 R_BuildLightMap(ent, surfaces + j);
13388                         }
13389                 }
13390         }
13391         if (update)
13392                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13393                         if (update[j])
13394                                 R_BuildLightMap(ent, surfaces + j);
13395         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13396         GL_AlphaTest(false);
13397
13398         // add to stats if desired
13399         if (r_speeds.integer && !skysurfaces && !depthonly)
13400         {
13401                 r_refdef.stats.entities_surfaces += numsurfacelist;
13402                 for (j = 0;j < numsurfacelist;j++)
13403                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
13404         }
13405
13406         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13407 }
13408
13409 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
13410 {
13411         static texture_t texture;
13412         static msurface_t surface;
13413         const msurface_t *surfacelist = &surface;
13414
13415         // fake enough texture and surface state to render this geometry
13416
13417         texture.update_lastrenderframe = -1; // regenerate this texture
13418         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
13419         texture.currentskinframe = skinframe;
13420         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
13421         texture.offsetmapping = OFFSETMAPPING_OFF;
13422         texture.offsetscale = 1;
13423         texture.specularscalemod = 1;
13424         texture.specularpowermod = 1;
13425
13426         surface.texture = &texture;
13427         surface.num_triangles = numtriangles;
13428         surface.num_firsttriangle = firsttriangle;
13429         surface.num_vertices = numvertices;
13430         surface.num_firstvertex = firstvertex;
13431
13432         // now render it
13433         rsurface.texture = R_GetCurrentTexture(surface.texture);
13434         rsurface.uselightmaptexture = false;
13435         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
13436 }
13437
13438 void R_DrawCustomSurface_Texture(texture_t *texture, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
13439 {
13440         static msurface_t surface;
13441         const msurface_t *surfacelist = &surface;
13442
13443         // fake enough texture and surface state to render this geometry
13444         surface.texture = texture;
13445         surface.num_triangles = numtriangles;
13446         surface.num_firsttriangle = firsttriangle;
13447         surface.num_vertices = numvertices;
13448         surface.num_firstvertex = firstvertex;
13449
13450         // now render it
13451         rsurface.texture = R_GetCurrentTexture(surface.texture);
13452         rsurface.uselightmaptexture = false;
13453         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
13454 }