]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
added GLES2 GLSL shader, work in progress (no warnings/errors in basic usage)
[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 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 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)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 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"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 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)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 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"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
74 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)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 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"};
78 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"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 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"};
81 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"};
82 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"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 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)"};
91 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)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
96
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
100
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 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."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 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."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 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"};
114 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"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
119 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"};
120
121 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
122 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
123 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
124 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
125 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
126 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
127 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
128 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
129
130 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)"};
131 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"};
132
133 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
138
139 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
140 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
141 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
142
143 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)"};
144 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
145 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
146 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
147 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
148 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)"};
149 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)"};
150 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)"};
151 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)"};
152 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)"};
153 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)"};
154 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)"};
155 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)"};
156
157 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)"};
158 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
159 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"};
160 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
161 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
162 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
163
164 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
165 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
166 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
167 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
168
169 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
170 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
171 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
172 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
173 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
174 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
175 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
176
177 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
178 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
179 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
180 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
181
182 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"};
183
184 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"};
185
186 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
187
188 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
189 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"};
190 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
191 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
192 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
193 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
194 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
195 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
196 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
197
198 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
199 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"};
200
201 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
202
203 extern cvar_t v_glslgamma;
204
205 extern qboolean v_flipped_state;
206
207 static struct r_bloomstate_s
208 {
209         qboolean enabled;
210         qboolean hdr;
211
212         int bloomwidth, bloomheight;
213
214         int screentexturewidth, screentextureheight;
215         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
216
217         int bloomtexturewidth, bloomtextureheight;
218         rtexture_t *texture_bloom;
219
220         // arrays for rendering the screen passes
221         float screentexcoord2f[8];
222         float bloomtexcoord2f[8];
223         float offsettexcoord2f[8];
224
225         r_viewport_t viewport;
226 }
227 r_bloomstate;
228
229 r_waterstate_t r_waterstate;
230
231 /// shadow volume bsp struct with automatically growing nodes buffer
232 svbsp_t r_svbsp;
233
234 rtexture_t *r_texture_blanknormalmap;
235 rtexture_t *r_texture_white;
236 rtexture_t *r_texture_grey128;
237 rtexture_t *r_texture_black;
238 rtexture_t *r_texture_notexture;
239 rtexture_t *r_texture_whitecube;
240 rtexture_t *r_texture_normalizationcube;
241 rtexture_t *r_texture_fogattenuation;
242 rtexture_t *r_texture_fogheighttexture;
243 rtexture_t *r_texture_gammaramps;
244 unsigned int r_texture_gammaramps_serial;
245 //rtexture_t *r_texture_fogintensity;
246 rtexture_t *r_texture_reflectcube;
247
248 // TODO: hash lookups?
249 typedef struct cubemapinfo_s
250 {
251         char basename[64];
252         rtexture_t *texture;
253 }
254 cubemapinfo_t;
255
256 int r_texture_numcubemaps;
257 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
258
259 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
260 unsigned int r_numqueries;
261 unsigned int r_maxqueries;
262
263 typedef struct r_qwskincache_s
264 {
265         char name[MAX_QPATH];
266         skinframe_t *skinframe;
267 }
268 r_qwskincache_t;
269
270 static r_qwskincache_t *r_qwskincache;
271 static int r_qwskincache_size;
272
273 /// vertex coordinates for a quad that covers the screen exactly
274 extern const float r_screenvertex3f[12];
275 extern const float r_d3dscreenvertex3f[12];
276 const float r_screenvertex3f[12] =
277 {
278         0, 0, 0,
279         1, 0, 0,
280         1, 1, 0,
281         0, 1, 0
282 };
283 const float r_d3dscreenvertex3f[12] =
284 {
285         0, 1, 0,
286         1, 1, 0,
287         1, 0, 0,
288         0, 0, 0
289 };
290
291 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
292 {
293         int i;
294         for (i = 0;i < verts;i++)
295         {
296                 out[0] = in[0] * r;
297                 out[1] = in[1] * g;
298                 out[2] = in[2] * b;
299                 out[3] = in[3];
300                 in += 4;
301                 out += 4;
302         }
303 }
304
305 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
306 {
307         int i;
308         for (i = 0;i < verts;i++)
309         {
310                 out[0] = r;
311                 out[1] = g;
312                 out[2] = b;
313                 out[3] = a;
314                 out += 4;
315         }
316 }
317
318 // FIXME: move this to client?
319 void FOG_clear(void)
320 {
321         if (gamemode == GAME_NEHAHRA)
322         {
323                 Cvar_Set("gl_fogenable", "0");
324                 Cvar_Set("gl_fogdensity", "0.2");
325                 Cvar_Set("gl_fogred", "0.3");
326                 Cvar_Set("gl_foggreen", "0.3");
327                 Cvar_Set("gl_fogblue", "0.3");
328         }
329         r_refdef.fog_density = 0;
330         r_refdef.fog_red = 0;
331         r_refdef.fog_green = 0;
332         r_refdef.fog_blue = 0;
333         r_refdef.fog_alpha = 1;
334         r_refdef.fog_start = 0;
335         r_refdef.fog_end = 16384;
336         r_refdef.fog_height = 1<<30;
337         r_refdef.fog_fadedepth = 128;
338         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
339 }
340
341 static void R_BuildBlankTextures(void)
342 {
343         unsigned char data[4];
344         data[2] = 128; // normal X
345         data[1] = 128; // normal Y
346         data[0] = 255; // normal Z
347         data[3] = 128; // height
348         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
349         data[0] = 255;
350         data[1] = 255;
351         data[2] = 255;
352         data[3] = 255;
353         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
354         data[0] = 128;
355         data[1] = 128;
356         data[2] = 128;
357         data[3] = 255;
358         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
359         data[0] = 0;
360         data[1] = 0;
361         data[2] = 0;
362         data[3] = 255;
363         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
364 }
365
366 static void R_BuildNoTexture(void)
367 {
368         int x, y;
369         unsigned char pix[16][16][4];
370         // this makes a light grey/dark grey checkerboard texture
371         for (y = 0;y < 16;y++)
372         {
373                 for (x = 0;x < 16;x++)
374                 {
375                         if ((y < 8) ^ (x < 8))
376                         {
377                                 pix[y][x][0] = 128;
378                                 pix[y][x][1] = 128;
379                                 pix[y][x][2] = 128;
380                                 pix[y][x][3] = 255;
381                         }
382                         else
383                         {
384                                 pix[y][x][0] = 64;
385                                 pix[y][x][1] = 64;
386                                 pix[y][x][2] = 64;
387                                 pix[y][x][3] = 255;
388                         }
389                 }
390         }
391         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
392 }
393
394 static void R_BuildWhiteCube(void)
395 {
396         unsigned char data[6*1*1*4];
397         memset(data, 255, sizeof(data));
398         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
399 }
400
401 static void R_BuildNormalizationCube(void)
402 {
403         int x, y, side;
404         vec3_t v;
405         vec_t s, t, intensity;
406 #define NORMSIZE 64
407         unsigned char *data;
408         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
409         for (side = 0;side < 6;side++)
410         {
411                 for (y = 0;y < NORMSIZE;y++)
412                 {
413                         for (x = 0;x < NORMSIZE;x++)
414                         {
415                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
416                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
417                                 switch(side)
418                                 {
419                                 default:
420                                 case 0:
421                                         v[0] = 1;
422                                         v[1] = -t;
423                                         v[2] = -s;
424                                         break;
425                                 case 1:
426                                         v[0] = -1;
427                                         v[1] = -t;
428                                         v[2] = s;
429                                         break;
430                                 case 2:
431                                         v[0] = s;
432                                         v[1] = 1;
433                                         v[2] = t;
434                                         break;
435                                 case 3:
436                                         v[0] = s;
437                                         v[1] = -1;
438                                         v[2] = -t;
439                                         break;
440                                 case 4:
441                                         v[0] = s;
442                                         v[1] = -t;
443                                         v[2] = 1;
444                                         break;
445                                 case 5:
446                                         v[0] = -s;
447                                         v[1] = -t;
448                                         v[2] = -1;
449                                         break;
450                                 }
451                                 intensity = 127.0f / sqrt(DotProduct(v, v));
452                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
453                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
454                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
455                                 data[((side*64+y)*64+x)*4+3] = 255;
456                         }
457                 }
458         }
459         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
460         Mem_Free(data);
461 }
462
463 static void R_BuildFogTexture(void)
464 {
465         int x, b;
466 #define FOGWIDTH 256
467         unsigned char data1[FOGWIDTH][4];
468         //unsigned char data2[FOGWIDTH][4];
469         double d, r, alpha;
470
471         r_refdef.fogmasktable_start = r_refdef.fog_start;
472         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
473         r_refdef.fogmasktable_range = r_refdef.fogrange;
474         r_refdef.fogmasktable_density = r_refdef.fog_density;
475
476         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
477         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
478         {
479                 d = (x * r - r_refdef.fogmasktable_start);
480                 if(developer_extra.integer)
481                         Con_DPrintf("%f ", d);
482                 d = max(0, d);
483                 if (r_fog_exp2.integer)
484                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
485                 else
486                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
487                 if(developer_extra.integer)
488                         Con_DPrintf(" : %f ", alpha);
489                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
490                 if(developer_extra.integer)
491                         Con_DPrintf(" = %f\n", alpha);
492                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
493         }
494
495         for (x = 0;x < FOGWIDTH;x++)
496         {
497                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
498                 data1[x][0] = b;
499                 data1[x][1] = b;
500                 data1[x][2] = b;
501                 data1[x][3] = 255;
502                 //data2[x][0] = 255 - b;
503                 //data2[x][1] = 255 - b;
504                 //data2[x][2] = 255 - b;
505                 //data2[x][3] = 255;
506         }
507         if (r_texture_fogattenuation)
508         {
509                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
510                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
511         }
512         else
513         {
514                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
515                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
516         }
517 }
518
519 static void R_BuildFogHeightTexture(void)
520 {
521         unsigned char *inpixels;
522         int size;
523         int x;
524         int y;
525         int j;
526         float c[4];
527         float f;
528         inpixels = NULL;
529         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
530         if (r_refdef.fogheighttexturename[0])
531                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
532         if (!inpixels)
533         {
534                 r_refdef.fog_height_tablesize = 0;
535                 if (r_texture_fogheighttexture)
536                         R_FreeTexture(r_texture_fogheighttexture);
537                 r_texture_fogheighttexture = NULL;
538                 if (r_refdef.fog_height_table2d)
539                         Mem_Free(r_refdef.fog_height_table2d);
540                 r_refdef.fog_height_table2d = NULL;
541                 if (r_refdef.fog_height_table1d)
542                         Mem_Free(r_refdef.fog_height_table1d);
543                 r_refdef.fog_height_table1d = NULL;
544                 return;
545         }
546         size = image_width;
547         r_refdef.fog_height_tablesize = size;
548         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
549         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
550         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
551         Mem_Free(inpixels);
552         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
553         // average fog color table accounting for every fog layer between a point
554         // and the camera.  (Note: attenuation is handled separately!)
555         for (y = 0;y < size;y++)
556         {
557                 for (x = 0;x < size;x++)
558                 {
559                         Vector4Clear(c);
560                         f = 0;
561                         if (x < y)
562                         {
563                                 for (j = x;j <= y;j++)
564                                 {
565                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
566                                         f++;
567                                 }
568                         }
569                         else
570                         {
571                                 for (j = x;j >= y;j--)
572                                 {
573                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
574                                         f++;
575                                 }
576                         }
577                         f = 1.0f / f;
578                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
579                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
580                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
581                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
582                 }
583         }
584         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
585 }
586
587 //=======================================================================================================================================================
588
589 static const char *builtinshaderstring =
590 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
591 "// written by Forest 'LordHavoc' Hale\n"
592 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
593 "\n"
594 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
595 "# define USEFOG\n"
596 "#endif\n"
597 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
598 "#define USELIGHTMAP\n"
599 "#endif\n"
600 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
601 "#define USEEYEVECTOR\n"
602 "#endif\n"
603 "\n"
604 "#ifdef USESHADOWMAP2D\n"
605 "# ifdef GL_EXT_gpu_shader4\n"
606 "#   extension GL_EXT_gpu_shader4 : enable\n"
607 "# endif\n"
608 "# ifdef GL_ARB_texture_gather\n"
609 "#   extension GL_ARB_texture_gather : enable\n"
610 "# else\n"
611 "#   ifdef GL_AMD_texture_texture4\n"
612 "#     extension GL_AMD_texture_texture4 : enable\n"
613 "#   endif\n"
614 "# endif\n"
615 "#endif\n"
616 "\n"
617 "//#ifdef USESHADOWSAMPLER\n"
618 "//# extension GL_ARB_shadow : enable\n"
619 "//#endif\n"
620 "\n"
621 "//#ifdef __GLSL_CG_DATA_TYPES\n"
622 "//# define myhalf half\n"
623 "//# define myhalf2 half2\n"
624 "//# define myhalf3 half3\n"
625 "//# define myhalf4 half4\n"
626 "//#else\n"
627 "# define myhalf float\n"
628 "# define myhalf2 vec2\n"
629 "# define myhalf3 vec3\n"
630 "# define myhalf4 vec4\n"
631 "//#endif\n"
632 "\n"
633 "#ifdef VERTEX_SHADER\n"
634 "uniform mat4 ModelViewProjectionMatrix;\n"
635 "#endif\n"
636 "\n"
637 "#ifdef MODE_DEPTH_OR_SHADOW\n"
638 "#ifdef VERTEX_SHADER\n"
639 "void main(void)\n"
640 "{\n"
641 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
642 "}\n"
643 "#endif\n"
644 "#else // !MODE_DEPTH_ORSHADOW\n"
645 "\n"
646 "\n"
647 "\n"
648 "\n"
649 "#ifdef MODE_SHOWDEPTH\n"
650 "#ifdef VERTEX_SHADER\n"
651 "void main(void)\n"
652 "{\n"
653 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
654 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
655 "}\n"
656 "#endif\n"
657 "\n"
658 "#ifdef FRAGMENT_SHADER\n"
659 "void main(void)\n"
660 "{\n"
661 "       gl_FragColor = gl_Color;\n"
662 "}\n"
663 "#endif\n"
664 "#else // !MODE_SHOWDEPTH\n"
665 "\n"
666 "\n"
667 "\n"
668 "\n"
669 "#ifdef MODE_POSTPROCESS\n"
670 "varying vec2 TexCoord1;\n"
671 "varying vec2 TexCoord2;\n"
672 "\n"
673 "#ifdef VERTEX_SHADER\n"
674 "void main(void)\n"
675 "{\n"
676 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
677 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
678 "#ifdef USEBLOOM\n"
679 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
680 "#endif\n"
681 "}\n"
682 "#endif\n"
683 "\n"
684 "#ifdef FRAGMENT_SHADER\n"
685 "uniform sampler2D Texture_First;\n"
686 "#ifdef USEBLOOM\n"
687 "uniform sampler2D Texture_Second;\n"
688 "uniform vec4 BloomColorSubtract;\n"
689 "#endif\n"
690 "#ifdef USEGAMMARAMPS\n"
691 "uniform sampler2D Texture_GammaRamps;\n"
692 "#endif\n"
693 "#ifdef USESATURATION\n"
694 "uniform float Saturation;\n"
695 "#endif\n"
696 "#ifdef USEVIEWTINT\n"
697 "uniform vec4 ViewTintColor;\n"
698 "#endif\n"
699 "//uncomment these if you want to use them:\n"
700 "uniform vec4 UserVec1;\n"
701 "uniform vec4 UserVec2;\n"
702 "// uniform vec4 UserVec3;\n"
703 "// uniform vec4 UserVec4;\n"
704 "// uniform float ClientTime;\n"
705 "uniform vec2 PixelSize;\n"
706 "void main(void)\n"
707 "{\n"
708 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
709 "#ifdef USEBLOOM\n"
710 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
711 "#endif\n"
712 "#ifdef USEVIEWTINT\n"
713 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
714 "#endif\n"
715 "\n"
716 "#ifdef USEPOSTPROCESSING\n"
717 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
718 "// 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"
719 "       float sobel = 1.0;\n"
720 "       // vec2 ts = textureSize(Texture_First, 0);\n"
721 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
722 "       vec2 px = PixelSize;\n"
723 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
724 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
725 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
726 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
727 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
728 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
729 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
730 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
731 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
732 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
733 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
734 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
735 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
736 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
737 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
738 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
739 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
740 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
741 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
742 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
743 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
744 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
745 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
746 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
747 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
748 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
749 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
750 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
751 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
752 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
753 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
754 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
755 "#endif\n"
756 "\n"
757 "#ifdef USESATURATION\n"
758 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
759 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
760 "       // 'vampire sight' effect, wheres red is compensated\n"
761 "       #ifdef SATURATION_REDCOMPENSATE\n"
762 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
763 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
764 "               gl_FragColor.r += rboost;\n"
765 "       #else\n"
766 "               // normal desaturation\n"
767 "               //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
768 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
769 "       #endif\n"
770 "#endif\n"
771 "\n"
772 "#ifdef USEGAMMARAMPS\n"
773 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
774 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
775 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
776 "#endif\n"
777 "}\n"
778 "#endif\n"
779 "#else // !MODE_POSTPROCESS\n"
780 "\n"
781 "\n"
782 "\n"
783 "\n"
784 "#ifdef MODE_GENERIC\n"
785 "#ifdef USEDIFFUSE\n"
786 "varying vec2 TexCoord1;\n"
787 "#endif\n"
788 "#ifdef USESPECULAR\n"
789 "varying vec2 TexCoord2;\n"
790 "#endif\n"
791 "#ifdef VERTEX_SHADER\n"
792 "void main(void)\n"
793 "{\n"
794 "       gl_FrontColor = gl_Color;\n"
795 "#ifdef USEDIFFUSE\n"
796 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
797 "#endif\n"
798 "#ifdef USESPECULAR\n"
799 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
800 "#endif\n"
801 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
802 "}\n"
803 "#endif\n"
804 "\n"
805 "#ifdef FRAGMENT_SHADER\n"
806 "#ifdef USEDIFFUSE\n"
807 "uniform sampler2D Texture_First;\n"
808 "#endif\n"
809 "#ifdef USESPECULAR\n"
810 "uniform sampler2D Texture_Second;\n"
811 "#endif\n"
812 "\n"
813 "void main(void)\n"
814 "{\n"
815 "#ifdef USEVIEWTINT\n"
816 "       gl_FragColor = gl_Color;\n"
817 "#else\n"
818 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
819 "#endif\n"
820 "#ifdef USEDIFFUSE\n"
821 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
822 "#endif\n"
823 "\n"
824 "#ifdef USESPECULAR\n"
825 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
826 "# ifdef USECOLORMAPPING\n"
827 "       gl_FragColor *= tex2;\n"
828 "# endif\n"
829 "# ifdef USEGLOW\n"
830 "       gl_FragColor += tex2;\n"
831 "# endif\n"
832 "# ifdef USEVERTEXTEXTUREBLEND\n"
833 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
834 "# endif\n"
835 "#endif\n"
836 "}\n"
837 "#endif\n"
838 "#else // !MODE_GENERIC\n"
839 "\n"
840 "\n"
841 "\n"
842 "\n"
843 "#ifdef MODE_BLOOMBLUR\n"
844 "varying TexCoord;\n"
845 "#ifdef VERTEX_SHADER\n"
846 "void main(void)\n"
847 "{\n"
848 "       gl_FrontColor = gl_Color;\n"
849 "       TexCoord = gl_MultiTexCoord0.xy;\n"
850 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
851 "}\n"
852 "#endif\n"
853 "\n"
854 "#ifdef FRAGMENT_SHADER\n"
855 "uniform sampler2D Texture_First;\n"
856 "uniform vec4 BloomBlur_Parameters;\n"
857 "\n"
858 "void main(void)\n"
859 "{\n"
860 "       int i;\n"
861 "       vec2 tc = TexCoord;\n"
862 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
863 "       tc += BloomBlur_Parameters.xy;\n"
864 "       for (i = 1;i < SAMPLES;i++)\n"
865 "       {\n"
866 "               color += texture2D(Texture_First, tc).rgb;\n"
867 "               tc += BloomBlur_Parameters.xy;\n"
868 "       }\n"
869 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
870 "}\n"
871 "#endif\n"
872 "#else // !MODE_BLOOMBLUR\n"
873 "#ifdef MODE_REFRACTION\n"
874 "varying vec2 TexCoord;\n"
875 "varying vec4 ModelViewProjectionPosition;\n"
876 "uniform mat4 TexMatrix;\n"
877 "#ifdef VERTEX_SHADER\n"
878 "\n"
879 "void main(void)\n"
880 "{\n"
881 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
882 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
883 "       ModelViewProjectionPosition = gl_Position;\n"
884 "}\n"
885 "#endif\n"
886 "\n"
887 "#ifdef FRAGMENT_SHADER\n"
888 "uniform sampler2D Texture_Normal;\n"
889 "uniform sampler2D Texture_Refraction;\n"
890 "uniform sampler2D Texture_Reflection;\n"
891 "\n"
892 "uniform vec4 DistortScaleRefractReflect;\n"
893 "uniform vec4 ScreenScaleRefractReflect;\n"
894 "uniform vec4 ScreenCenterRefractReflect;\n"
895 "uniform vec4 RefractColor;\n"
896 "uniform vec4 ReflectColor;\n"
897 "uniform float ReflectFactor;\n"
898 "uniform float ReflectOffset;\n"
899 "\n"
900 "void main(void)\n"
901 "{\n"
902 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
903 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
904 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
905 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
906 "       // FIXME temporary hack to detect the case that the reflection\n"
907 "       // gets blackened at edges due to leaving the area that contains actual\n"
908 "       // content.\n"
909 "       // Remove this 'ack once we have a better way to stop this thing from\n"
910 "       // 'appening.\n"
911 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
912 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
913 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
914 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
915 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
916 "       gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
917 "}\n"
918 "#endif\n"
919 "#else // !MODE_REFRACTION\n"
920 "\n"
921 "\n"
922 "\n"
923 "\n"
924 "#ifdef MODE_WATER\n"
925 "varying vec2 TexCoord;\n"
926 "varying vec3 EyeVector;\n"
927 "varying vec4 ModelViewProjectionPosition;\n"
928 "#ifdef VERTEX_SHADER\n"
929 "uniform vec3 EyePosition;\n"
930 "uniform mat4 TexMatrix;\n"
931 "\n"
932 "void main(void)\n"
933 "{\n"
934 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
935 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
936 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
937 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
938 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
939 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
940 "       ModelViewProjectionPosition = gl_Position;\n"
941 "}\n"
942 "#endif\n"
943 "\n"
944 "#ifdef FRAGMENT_SHADER\n"
945 "uniform sampler2D Texture_Normal;\n"
946 "uniform sampler2D Texture_Refraction;\n"
947 "uniform sampler2D Texture_Reflection;\n"
948 "\n"
949 "uniform vec4 DistortScaleRefractReflect;\n"
950 "uniform vec4 ScreenScaleRefractReflect;\n"
951 "uniform vec4 ScreenCenterRefractReflect;\n"
952 "uniform vec4 RefractColor;\n"
953 "uniform vec4 ReflectColor;\n"
954 "uniform float ReflectFactor;\n"
955 "uniform float ReflectOffset;\n"
956 "uniform float ClientTime;\n"
957 "#ifdef USENORMALMAPSCROLLBLEND\n"
958 "uniform vec2 NormalmapScrollBlend;\n"
959 "#endif\n"
960 "\n"
961 "void main(void)\n"
962 "{\n"
963 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
964 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
965 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
966 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
967 "       // slight water animation via 2 layer scrolling (todo: tweak)\n"
968 "       #ifdef USENORMALMAPSCROLLBLEND\n"
969 "               vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
970 "               normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
971 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
972 "       #else\n"
973 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
974 "       #endif\n"
975 "       // FIXME temporary hack to detect the case that the reflection\n"
976 "       // gets blackened at edges due to leaving the area that contains actual\n"
977 "       // content.\n"
978 "       // Remove this 'ack once we have a better way to stop this thing from\n"
979 "       // 'appening.\n"
980 "       float f  = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
981 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
982 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
983 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
984 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
985 "       f  = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
986 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
987 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
988 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
989 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
990 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
991 "       gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
992 "}\n"
993 "#endif\n"
994 "#else // !MODE_WATER\n"
995 "\n"
996 "\n"
997 "\n"
998 "\n"
999 "// common definitions between vertex shader and fragment shader:\n"
1000 "\n"
1001 "varying vec2 TexCoord;\n"
1002 "#ifdef USEVERTEXTEXTUREBLEND\n"
1003 "varying vec2 TexCoord2;\n"
1004 "#endif\n"
1005 "#ifdef USELIGHTMAP\n"
1006 "varying vec2 TexCoordLightmap;\n"
1007 "#endif\n"
1008 "\n"
1009 "#ifdef MODE_LIGHTSOURCE\n"
1010 "varying vec3 CubeVector;\n"
1011 "#endif\n"
1012 "\n"
1013 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1014 "varying vec3 LightVector;\n"
1015 "#endif\n"
1016 "\n"
1017 "#ifdef USEEYEVECTOR\n"
1018 "varying vec3 EyeVector;\n"
1019 "#endif\n"
1020 "#ifdef USEFOG\n"
1021 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1022 "#endif\n"
1023 "\n"
1024 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1025 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1026 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1027 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1028 "#endif\n"
1029 "\n"
1030 "#ifdef USEREFLECTION\n"
1031 "varying vec4 ModelViewProjectionPosition;\n"
1032 "#endif\n"
1033 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1034 "uniform vec3 LightPosition;\n"
1035 "varying vec4 ModelViewPosition;\n"
1036 "#endif\n"
1037 "\n"
1038 "#ifdef MODE_LIGHTSOURCE\n"
1039 "uniform vec3 LightPosition;\n"
1040 "#endif\n"
1041 "uniform vec3 EyePosition;\n"
1042 "#ifdef MODE_LIGHTDIRECTION\n"
1043 "uniform vec3 LightDir;\n"
1044 "#endif\n"
1045 "uniform vec4 FogPlane;\n"
1046 "\n"
1047 "#ifdef USESHADOWMAPORTHO\n"
1048 "varying vec3 ShadowMapTC;\n"
1049 "#endif\n"
1050 "\n"
1051 "\n"
1052 "\n"
1053 "\n"
1054 "\n"
1055 "// 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"
1056 "\n"
1057 "// fragment shader specific:\n"
1058 "#ifdef FRAGMENT_SHADER\n"
1059 "\n"
1060 "uniform sampler2D Texture_Normal;\n"
1061 "uniform sampler2D Texture_Color;\n"
1062 "uniform sampler2D Texture_Gloss;\n"
1063 "#ifdef USEGLOW\n"
1064 "uniform sampler2D Texture_Glow;\n"
1065 "#endif\n"
1066 "#ifdef USEVERTEXTEXTUREBLEND\n"
1067 "uniform sampler2D Texture_SecondaryNormal;\n"
1068 "uniform sampler2D Texture_SecondaryColor;\n"
1069 "uniform sampler2D Texture_SecondaryGloss;\n"
1070 "#ifdef USEGLOW\n"
1071 "uniform sampler2D Texture_SecondaryGlow;\n"
1072 "#endif\n"
1073 "#endif\n"
1074 "#ifdef USECOLORMAPPING\n"
1075 "uniform sampler2D Texture_Pants;\n"
1076 "uniform sampler2D Texture_Shirt;\n"
1077 "#endif\n"
1078 "#ifdef USEFOG\n"
1079 "#ifdef USEFOGHEIGHTTEXTURE\n"
1080 "uniform sampler2D Texture_FogHeightTexture;\n"
1081 "#endif\n"
1082 "uniform sampler2D Texture_FogMask;\n"
1083 "#endif\n"
1084 "#ifdef USELIGHTMAP\n"
1085 "uniform sampler2D Texture_Lightmap;\n"
1086 "#endif\n"
1087 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1088 "uniform sampler2D Texture_Deluxemap;\n"
1089 "#endif\n"
1090 "#ifdef USEREFLECTION\n"
1091 "uniform sampler2D Texture_Reflection;\n"
1092 "#endif\n"
1093 "\n"
1094 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1095 "uniform sampler2D Texture_ScreenDepth;\n"
1096 "uniform sampler2D Texture_ScreenNormalMap;\n"
1097 "#endif\n"
1098 "#ifdef USEDEFERREDLIGHTMAP\n"
1099 "uniform sampler2D Texture_ScreenDiffuse;\n"
1100 "uniform sampler2D Texture_ScreenSpecular;\n"
1101 "#endif\n"
1102 "\n"
1103 "uniform myhalf3 Color_Pants;\n"
1104 "uniform myhalf3 Color_Shirt;\n"
1105 "uniform myhalf3 FogColor;\n"
1106 "\n"
1107 "#ifdef USEFOG\n"
1108 "uniform float FogRangeRecip;\n"
1109 "uniform float FogPlaneViewDist;\n"
1110 "uniform float FogHeightFade;\n"
1111 "vec3 FogVertex(vec3 surfacecolor)\n"
1112 "{\n"
1113 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1114 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1115 "       float fogfrac;\n"
1116 "#ifdef USEFOGHEIGHTTEXTURE\n"
1117 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1118 "       fogfrac = fogheightpixel.a;\n"
1119 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1120 "#else\n"
1121 "# ifdef USEFOGOUTSIDE\n"
1122 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1123 "# else\n"
1124 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1125 "# endif\n"
1126 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1127 "#endif\n"
1128 "}\n"
1129 "#endif\n"
1130 "\n"
1131 "#ifdef USEOFFSETMAPPING\n"
1132 "uniform float OffsetMapping_Scale;\n"
1133 "vec2 OffsetMapping(vec2 TexCoord)\n"
1134 "{\n"
1135 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1136 "       // 14 sample relief mapping: linear search and then binary search\n"
1137 "       // this basically steps forward a small amount repeatedly until it finds\n"
1138 "       // itself inside solid, then jitters forward and back using decreasing\n"
1139 "       // amounts to find the impact\n"
1140 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1141 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1142 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1143 "       vec3 RT = vec3(TexCoord, 1);\n"
1144 "       OffsetVector *= 0.1;\n"
1145 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1146 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1147 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1148 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1149 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1150 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1151 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1152 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1153 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1154 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1155 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1156 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1157 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1158 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1159 "       return RT.xy;\n"
1160 "#else\n"
1161 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1162 "       // this basically moves forward the full distance, and then backs up based\n"
1163 "       // on height of samples\n"
1164 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1165 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1166 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1167 "       TexCoord += OffsetVector;\n"
1168 "       OffsetVector *= 0.5;\n"
1169 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1170 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1171 "       return TexCoord;\n"
1172 "#endif\n"
1173 "}\n"
1174 "#endif // USEOFFSETMAPPING\n"
1175 "\n"
1176 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1177 "uniform sampler2D Texture_Attenuation;\n"
1178 "uniform samplerCube Texture_Cube;\n"
1179 "#endif\n"
1180 "\n"
1181 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1182 "\n"
1183 "#ifdef USESHADOWMAP2D\n"
1184 "# ifdef USESHADOWSAMPLER\n"
1185 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1186 "# else\n"
1187 "uniform sampler2D Texture_ShadowMap2D;\n"
1188 "# endif\n"
1189 "#endif\n"
1190 "\n"
1191 "#ifdef USESHADOWMAPVSDCT\n"
1192 "uniform samplerCube Texture_CubeProjection;\n"
1193 "#endif\n"
1194 "\n"
1195 "#if defined(USESHADOWMAP2D)\n"
1196 "uniform vec2 ShadowMap_TextureScale;\n"
1197 "uniform vec4 ShadowMap_Parameters;\n"
1198 "#endif\n"
1199 "\n"
1200 "#if defined(USESHADOWMAP2D)\n"
1201 "# ifdef USESHADOWMAPORTHO\n"
1202 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1203 "# else\n"
1204 "#  ifdef USESHADOWMAPVSDCT\n"
1205 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1206 "{\n"
1207 "       vec3 adir = abs(dir);\n"
1208 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1209 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1210 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1211 "}\n"
1212 "#  else\n"
1213 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1214 "{\n"
1215 "       vec3 adir = abs(dir);\n"
1216 "       float ma = adir.z;\n"
1217 "       vec4 proj = vec4(dir, 2.5);\n"
1218 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1219 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1220 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1221 "       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"
1222 "}\n"
1223 "#  endif\n"
1224 "# endif\n"
1225 "#endif // defined(USESHADOWMAP2D)\n"
1226 "\n"
1227 "# ifdef USESHADOWMAP2D\n"
1228 "float ShadowMapCompare(vec3 dir)\n"
1229 "{\n"
1230 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1231 "       float f;\n"
1232 "\n"
1233 "#  ifdef USESHADOWSAMPLER\n"
1234 "#    ifdef USESHADOWMAPPCF\n"
1235 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1236 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1237 "       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"
1238 "#    else\n"
1239 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1240 "#    endif\n"
1241 "#  else\n"
1242 "#    ifdef USESHADOWMAPPCF\n"
1243 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1244 "#      ifdef GL_ARB_texture_gather\n"
1245 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1246 "#      else\n"
1247 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1248 "#      endif\n"
1249 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1250 "#      if USESHADOWMAPPCF > 1\n"
1251 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1252 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1253 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1254 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1255 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1256 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1257 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1258 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1259 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1260 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1261 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1262 "       locols.yz += group2.ab;\n"
1263 "       hicols.yz += group8.rg;\n"
1264 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1265 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1266 "                               mix(locols, hicols, offset.y);\n"
1267 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1268 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1269 "       f = dot(cols, vec4(1.0/25.0));\n"
1270 "#      else\n"
1271 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1272 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1273 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1274 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1275 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1276 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1277 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1278 "#      endif\n"
1279 "#     else\n"
1280 "#      ifdef GL_EXT_gpu_shader4\n"
1281 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1282 "#      else\n"
1283 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1284 "#      endif\n"
1285 "#      if USESHADOWMAPPCF > 1\n"
1286 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1287 "       center *= ShadowMap_TextureScale;\n"
1288 "       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"
1289 "       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"
1290 "       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"
1291 "       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"
1292 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1293 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1294 "#      else\n"
1295 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1296 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1297 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1298 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1299 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1300 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1301 "#      endif\n"
1302 "#     endif\n"
1303 "#    else\n"
1304 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1305 "#    endif\n"
1306 "#  endif\n"
1307 "#  ifdef USESHADOWMAPORTHO\n"
1308 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1309 "#  else\n"
1310 "       return f;\n"
1311 "#  endif\n"
1312 "}\n"
1313 "# endif\n"
1314 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1315 "#endif // FRAGMENT_SHADER\n"
1316 "\n"
1317 "\n"
1318 "\n"
1319 "\n"
1320 "#ifdef MODE_DEFERREDGEOMETRY\n"
1321 "#ifdef VERTEX_SHADER\n"
1322 "uniform mat4 TexMatrix;\n"
1323 "#ifdef USEVERTEXTEXTUREBLEND\n"
1324 "uniform mat4 BackgroundTexMatrix;\n"
1325 "#endif\n"
1326 "uniform mat4 ModelViewMatrix;\n"
1327 "void main(void)\n"
1328 "{\n"
1329 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1330 "#ifdef USEVERTEXTEXTUREBLEND\n"
1331 "       gl_FrontColor = gl_Color;\n"
1332 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1333 "#endif\n"
1334 "\n"
1335 "       // transform unnormalized eye direction into tangent space\n"
1336 "#ifdef USEOFFSETMAPPING\n"
1337 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1338 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1339 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1340 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1341 "#endif\n"
1342 "\n"
1343 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1344 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1345 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1346 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1347 "}\n"
1348 "#endif // VERTEX_SHADER\n"
1349 "\n"
1350 "#ifdef FRAGMENT_SHADER\n"
1351 "void main(void)\n"
1352 "{\n"
1353 "#ifdef USEOFFSETMAPPING\n"
1354 "       // apply offsetmapping\n"
1355 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1356 "#define TexCoord TexCoordOffset\n"
1357 "#endif\n"
1358 "\n"
1359 "#ifdef USEALPHAKILL\n"
1360 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1361 "               discard;\n"
1362 "#endif\n"
1363 "\n"
1364 "#ifdef USEVERTEXTEXTUREBLEND\n"
1365 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1366 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1367 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1368 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1369 "#endif\n"
1370 "\n"
1371 "#ifdef USEVERTEXTEXTUREBLEND\n"
1372 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1373 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1374 "#else\n"
1375 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1376 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1377 "#endif\n"
1378 "\n"
1379 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1380 "}\n"
1381 "#endif // FRAGMENT_SHADER\n"
1382 "#else // !MODE_DEFERREDGEOMETRY\n"
1383 "\n"
1384 "\n"
1385 "\n"
1386 "\n"
1387 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1388 "#ifdef VERTEX_SHADER\n"
1389 "uniform mat4 ModelViewMatrix;\n"
1390 "void main(void)\n"
1391 "{\n"
1392 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1393 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1394 "}\n"
1395 "#endif // VERTEX_SHADER\n"
1396 "\n"
1397 "#ifdef FRAGMENT_SHADER\n"
1398 "uniform mat4 ViewToLight;\n"
1399 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1400 "uniform vec2 ScreenToDepth;\n"
1401 "uniform myhalf3 DeferredColor_Ambient;\n"
1402 "uniform myhalf3 DeferredColor_Diffuse;\n"
1403 "#ifdef USESPECULAR\n"
1404 "uniform myhalf3 DeferredColor_Specular;\n"
1405 "uniform myhalf SpecularPower;\n"
1406 "#endif\n"
1407 "uniform myhalf2 PixelToScreenTexCoord;\n"
1408 "void main(void)\n"
1409 "{\n"
1410 "       // calculate viewspace pixel position\n"
1411 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1412 "       vec3 position;\n"
1413 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1414 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1415 "       // decode viewspace pixel normal\n"
1416 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1417 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1418 "       // surfacenormal = pixel normal in viewspace\n"
1419 "       // LightVector = pixel to light in viewspace\n"
1420 "       // CubeVector = position in lightspace\n"
1421 "       // eyevector = pixel to view in viewspace\n"
1422 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1423 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1424 "#ifdef USEDIFFUSE\n"
1425 "       // calculate diffuse shading\n"
1426 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1427 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1428 "#endif\n"
1429 "#ifdef USESPECULAR\n"
1430 "       // calculate directional shading\n"
1431 "       vec3 eyevector = position * -1.0;\n"
1432 "#  ifdef USEEXACTSPECULARMATH\n"
1433 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1434 "#  else\n"
1435 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1436 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1437 "#  endif\n"
1438 "#endif\n"
1439 "\n"
1440 "#if defined(USESHADOWMAP2D)\n"
1441 "       fade *= ShadowMapCompare(CubeVector);\n"
1442 "#endif\n"
1443 "\n"
1444 "#ifdef USEDIFFUSE\n"
1445 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1446 "#else\n"
1447 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1448 "#endif\n"
1449 "#ifdef USESPECULAR\n"
1450 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1451 "#else\n"
1452 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1453 "#endif\n"
1454 "\n"
1455 "# ifdef USECUBEFILTER\n"
1456 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1457 "       gl_FragData[0].rgb *= cubecolor;\n"
1458 "       gl_FragData[1].rgb *= cubecolor;\n"
1459 "# endif\n"
1460 "}\n"
1461 "#endif // FRAGMENT_SHADER\n"
1462 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1463 "\n"
1464 "\n"
1465 "\n"
1466 "\n"
1467 "#ifdef VERTEX_SHADER\n"
1468 "uniform mat4 TexMatrix;\n"
1469 "#ifdef USEVERTEXTEXTUREBLEND\n"
1470 "uniform mat4 BackgroundTexMatrix;\n"
1471 "#endif\n"
1472 "#ifdef MODE_LIGHTSOURCE\n"
1473 "uniform mat4 ModelToLight;\n"
1474 "#endif\n"
1475 "#ifdef USESHADOWMAPORTHO\n"
1476 "uniform mat4 ShadowMapMatrix;\n"
1477 "#endif\n"
1478 "void main(void)\n"
1479 "{\n"
1480 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1481 "       gl_FrontColor = gl_Color;\n"
1482 "#endif\n"
1483 "       // copy the surface texcoord\n"
1484 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1485 "#ifdef USEVERTEXTEXTUREBLEND\n"
1486 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1487 "#endif\n"
1488 "#ifdef USELIGHTMAP\n"
1489 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1490 "#endif\n"
1491 "\n"
1492 "#ifdef MODE_LIGHTSOURCE\n"
1493 "       // transform vertex position into light attenuation/cubemap space\n"
1494 "       // (-1 to +1 across the light box)\n"
1495 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1496 "\n"
1497 "# ifdef USEDIFFUSE\n"
1498 "       // transform unnormalized light direction into tangent space\n"
1499 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1500 "       //  normalize it per pixel)\n"
1501 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1502 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1503 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1504 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1505 "# endif\n"
1506 "#endif\n"
1507 "\n"
1508 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1509 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1510 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1511 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1512 "#endif\n"
1513 "\n"
1514 "       // transform unnormalized eye direction into tangent space\n"
1515 "#ifdef USEEYEVECTOR\n"
1516 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1517 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1518 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1519 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1520 "#endif\n"
1521 "\n"
1522 "#ifdef USEFOG\n"
1523 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1524 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1525 "#endif\n"
1526 "\n"
1527 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1528 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1529 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1530 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1531 "#endif\n"
1532 "\n"
1533 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1534 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1535 "\n"
1536 "#ifdef USESHADOWMAPORTHO\n"
1537 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1538 "#endif\n"
1539 "\n"
1540 "#ifdef USEREFLECTION\n"
1541 "       ModelViewProjectionPosition = gl_Position;\n"
1542 "#endif\n"
1543 "}\n"
1544 "#endif // VERTEX_SHADER\n"
1545 "\n"
1546 "\n"
1547 "\n"
1548 "\n"
1549 "#ifdef FRAGMENT_SHADER\n"
1550 "#ifdef USEDEFERREDLIGHTMAP\n"
1551 "uniform myhalf2 PixelToScreenTexCoord;\n"
1552 "uniform myhalf3 DeferredMod_Diffuse;\n"
1553 "uniform myhalf3 DeferredMod_Specular;\n"
1554 "#endif\n"
1555 "uniform myhalf3 Color_Ambient;\n"
1556 "uniform myhalf3 Color_Diffuse;\n"
1557 "uniform myhalf3 Color_Specular;\n"
1558 "uniform myhalf SpecularPower;\n"
1559 "#ifdef USEGLOW\n"
1560 "uniform myhalf3 Color_Glow;\n"
1561 "#endif\n"
1562 "uniform myhalf Alpha;\n"
1563 "#ifdef USEREFLECTION\n"
1564 "uniform vec4 DistortScaleRefractReflect;\n"
1565 "uniform vec4 ScreenScaleRefractReflect;\n"
1566 "uniform vec4 ScreenCenterRefractReflect;\n"
1567 "uniform myhalf4 ReflectColor;\n"
1568 "#endif\n"
1569 "#ifdef USEREFLECTCUBE\n"
1570 "uniform mat4 ModelToReflectCube;\n"
1571 "uniform sampler2D Texture_ReflectMask;\n"
1572 "uniform samplerCube Texture_ReflectCube;\n"
1573 "#endif\n"
1574 "#ifdef MODE_LIGHTDIRECTION\n"
1575 "uniform myhalf3 LightColor;\n"
1576 "#endif\n"
1577 "#ifdef MODE_LIGHTSOURCE\n"
1578 "uniform myhalf3 LightColor;\n"
1579 "#endif\n"
1580 "void main(void)\n"
1581 "{\n"
1582 "#ifdef USEOFFSETMAPPING\n"
1583 "       // apply offsetmapping\n"
1584 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1585 "#define TexCoord TexCoordOffset\n"
1586 "#endif\n"
1587 "\n"
1588 "       // combine the diffuse textures (base, pants, shirt)\n"
1589 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1590 "#ifdef USEALPHAKILL\n"
1591 "       if (color.a < 0.5)\n"
1592 "               discard;\n"
1593 "#endif\n"
1594 "       color.a *= Alpha;\n"
1595 "#ifdef USECOLORMAPPING\n"
1596 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1597 "#endif\n"
1598 "#ifdef USEVERTEXTEXTUREBLEND\n"
1599 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1600 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1601 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1602 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1603 "       color.a = 1.0;\n"
1604 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1605 "#endif\n"
1606 "\n"
1607 "       // get the surface normal\n"
1608 "#ifdef USEVERTEXTEXTUREBLEND\n"
1609 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1610 "#else\n"
1611 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1612 "#endif\n"
1613 "\n"
1614 "       // get the material colors\n"
1615 "       myhalf3 diffusetex = color.rgb;\n"
1616 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1617 "# ifdef USEVERTEXTEXTUREBLEND\n"
1618 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1619 "# else\n"
1620 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1621 "# endif\n"
1622 "#endif\n"
1623 "\n"
1624 "#ifdef USEREFLECTCUBE\n"
1625 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1626 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1627 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1628 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1629 "#endif\n"
1630 "\n"
1631 "\n"
1632 "\n"
1633 "\n"
1634 "#ifdef MODE_LIGHTSOURCE\n"
1635 "       // light source\n"
1636 "#ifdef USEDIFFUSE\n"
1637 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1638 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1639 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1640 "#ifdef USESPECULAR\n"
1641 "#ifdef USEEXACTSPECULARMATH\n"
1642 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1643 "#else\n"
1644 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1645 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1646 "#endif\n"
1647 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1648 "#endif\n"
1649 "#else\n"
1650 "       color.rgb = diffusetex * Color_Ambient;\n"
1651 "#endif\n"
1652 "       color.rgb *= LightColor;\n"
1653 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1654 "#if defined(USESHADOWMAP2D)\n"
1655 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1656 "#endif\n"
1657 "# ifdef USECUBEFILTER\n"
1658 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1659 "# endif\n"
1660 "#endif // MODE_LIGHTSOURCE\n"
1661 "\n"
1662 "\n"
1663 "\n"
1664 "\n"
1665 "#ifdef MODE_LIGHTDIRECTION\n"
1666 "#define SHADING\n"
1667 "#ifdef USEDIFFUSE\n"
1668 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1669 "#endif\n"
1670 "#define lightcolor LightColor\n"
1671 "#endif // MODE_LIGHTDIRECTION\n"
1672 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1673 "#define SHADING\n"
1674 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1675 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1676 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1677 "       // convert modelspace light vector to tangentspace\n"
1678 "       myhalf3 lightnormal;\n"
1679 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1680 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1681 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1682 "       lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1683 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1684 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1685 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1686 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1687 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1688 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1689 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1690 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1691 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1692 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1693 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1694 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1695 "#define SHADING\n"
1696 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1697 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1698 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1699 "#endif\n"
1700 "\n"
1701 "\n"
1702 "\n"
1703 "\n"
1704 "#ifdef MODE_FAKELIGHT\n"
1705 "#define SHADING\n"
1706 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1707 "myhalf3 lightcolor = myhalf3(1.0);\n"
1708 "#endif // MODE_FAKELIGHT\n"
1709 "\n"
1710 "\n"
1711 "\n"
1712 "\n"
1713 "#ifdef MODE_LIGHTMAP\n"
1714 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1715 "#endif // MODE_LIGHTMAP\n"
1716 "#ifdef MODE_VERTEXCOLOR\n"
1717 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1718 "#endif // MODE_VERTEXCOLOR\n"
1719 "#ifdef MODE_FLATCOLOR\n"
1720 "       color.rgb = diffusetex * Color_Ambient;\n"
1721 "#endif // MODE_FLATCOLOR\n"
1722 "\n"
1723 "\n"
1724 "\n"
1725 "\n"
1726 "#ifdef SHADING\n"
1727 "# ifdef USEDIFFUSE\n"
1728 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1729 "#  ifdef USESPECULAR\n"
1730 "#   ifdef USEEXACTSPECULARMATH\n"
1731 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1732 "#   else\n"
1733 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1734 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1735 "#   endif\n"
1736 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1737 "#  else\n"
1738 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1739 "#  endif\n"
1740 "# else\n"
1741 "       color.rgb = diffusetex * Color_Ambient;\n"
1742 "# endif\n"
1743 "#endif\n"
1744 "\n"
1745 "#ifdef USESHADOWMAPORTHO\n"
1746 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1747 "#endif\n"
1748 "\n"
1749 "#ifdef USEDEFERREDLIGHTMAP\n"
1750 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1751 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1752 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1753 "#endif\n"
1754 "\n"
1755 "#ifdef USEGLOW\n"
1756 "#ifdef USEVERTEXTEXTUREBLEND\n"
1757 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1758 "#else\n"
1759 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1760 "#endif\n"
1761 "#endif\n"
1762 "\n"
1763 "#ifdef USEFOG\n"
1764 "       color.rgb = FogVertex(color.rgb);\n"
1765 "#endif\n"
1766 "\n"
1767 "       // 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"
1768 "#ifdef USEREFLECTION\n"
1769 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1770 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1771 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1772 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1773 "       // FIXME temporary hack to detect the case that the reflection\n"
1774 "       // gets blackened at edges due to leaving the area that contains actual\n"
1775 "       // content.\n"
1776 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1777 "       // 'appening.\n"
1778 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1779 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1780 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1781 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1782 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1783 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1784 "#endif\n"
1785 "\n"
1786 "       gl_FragColor = vec4(color);\n"
1787 "}\n"
1788 "#endif // FRAGMENT_SHADER\n"
1789 "\n"
1790 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1791 "#endif // !MODE_DEFERREDGEOMETRY\n"
1792 "#endif // !MODE_WATER\n"
1793 "#endif // !MODE_REFRACTION\n"
1794 "#endif // !MODE_BLOOMBLUR\n"
1795 "#endif // !MODE_GENERIC\n"
1796 "#endif // !MODE_POSTPROCESS\n"
1797 "#endif // !MODE_SHOWDEPTH\n"
1798 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1799 ;
1800
1801 /*
1802 =========================================================================================================================================================
1803
1804
1805
1806 =========================================================================================================================================================
1807
1808
1809
1810 =========================================================================================================================================================
1811
1812
1813
1814 =========================================================================================================================================================
1815
1816
1817
1818 =========================================================================================================================================================
1819
1820
1821
1822 =========================================================================================================================================================
1823
1824
1825
1826 =========================================================================================================================================================
1827 */
1828
1829 const char *builtincgshaderstring =
1830 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1831 "// written by Forest 'LordHavoc' Hale\n"
1832 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1833 "\n"
1834 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1835 "#if defined(USEREFLECTION)\n"
1836 "#undef USESHADOWMAPORTHO\n"
1837 "#endif\n"
1838 "\n"
1839 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1840 "# define USEFOG\n"
1841 "#endif\n"
1842 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1843 "#define USELIGHTMAP\n"
1844 "#endif\n"
1845 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1846 "#define USEEYEVECTOR\n"
1847 "#endif\n"
1848 "\n"
1849 "#ifdef FRAGMENT_SHADER\n"
1850 "#ifdef HLSL\n"
1851 "//#undef USESHADOWMAPPCF\n"
1852 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1853 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1854 "#else\n"
1855 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1856 "#endif\n"
1857 "#endif\n"
1858 "\n"
1859 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1860 "#ifdef VERTEX_SHADER\n"
1861 "void main\n"
1862 "(\n"
1863 "float4 gl_Vertex : POSITION,\n"
1864 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1865 "out float4 gl_Position : POSITION,\n"
1866 "out float Depth : TEXCOORD0\n"
1867 ")\n"
1868 "{\n"
1869 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1870 "       Depth = gl_Position.z;\n"
1871 "}\n"
1872 "#endif\n"
1873 "\n"
1874 "#ifdef FRAGMENT_SHADER\n"
1875 "void main\n"
1876 "(\n"
1877 "float Depth : TEXCOORD0,\n"
1878 "out float4 gl_FragColor : COLOR\n"
1879 ")\n"
1880 "{\n"
1881 "//     float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1882 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1883 "       temp.yz -= floor(temp.yz);\n"
1884 "       gl_FragColor = temp;\n"
1885 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1886 "}\n"
1887 "#endif\n"
1888 "#else // !MODE_DEPTH_ORSHADOW\n"
1889 "\n"
1890 "\n"
1891 "\n"
1892 "\n"
1893 "#ifdef MODE_SHOWDEPTH\n"
1894 "#ifdef VERTEX_SHADER\n"
1895 "void main\n"
1896 "(\n"
1897 "float4 gl_Vertex : POSITION,\n"
1898 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1899 "out float4 gl_Position : POSITION,\n"
1900 "out float4 gl_FrontColor : COLOR0\n"
1901 ")\n"
1902 "{\n"
1903 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1904 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1905 "}\n"
1906 "#endif\n"
1907 "\n"
1908 "#ifdef FRAGMENT_SHADER\n"
1909 "void main\n"
1910 "(\n"
1911 "float4 gl_FrontColor : COLOR0,\n"
1912 "out float4 gl_FragColor : COLOR\n"
1913 ")\n"
1914 "{\n"
1915 "       gl_FragColor = gl_FrontColor;\n"
1916 "}\n"
1917 "#endif\n"
1918 "#else // !MODE_SHOWDEPTH\n"
1919 "\n"
1920 "\n"
1921 "\n"
1922 "\n"
1923 "#ifdef MODE_POSTPROCESS\n"
1924 "\n"
1925 "#ifdef VERTEX_SHADER\n"
1926 "void main\n"
1927 "(\n"
1928 "float4 gl_Vertex : POSITION,\n"
1929 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1930 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1931 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1932 "out float4 gl_Position : POSITION,\n"
1933 "out float2 TexCoord1 : TEXCOORD0,\n"
1934 "out float2 TexCoord2 : TEXCOORD1\n"
1935 ")\n"
1936 "{\n"
1937 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1938 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1939 "#ifdef USEBLOOM\n"
1940 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1941 "#endif\n"
1942 "}\n"
1943 "#endif\n"
1944 "\n"
1945 "#ifdef FRAGMENT_SHADER\n"
1946 "void main\n"
1947 "(\n"
1948 "float2 TexCoord1 : TEXCOORD0,\n"
1949 "float2 TexCoord2 : TEXCOORD1,\n"
1950 "uniform sampler Texture_First : register(s0),\n"
1951 "#ifdef USEBLOOM\n"
1952 "uniform sampler Texture_Second : register(s1),\n"
1953 "#endif\n"
1954 "#ifdef USEGAMMARAMPS\n"
1955 "uniform sampler Texture_GammaRamps : register(s2),\n"
1956 "#endif\n"
1957 "#ifdef USESATURATION\n"
1958 "uniform float Saturation : register(c30),\n"
1959 "#endif\n"
1960 "#ifdef USEVIEWTINT\n"
1961 "uniform float4 ViewTintColor : register(c41),\n"
1962 "#endif\n"
1963 "uniform float4 UserVec1 : register(c37),\n"
1964 "uniform float4 UserVec2 : register(c38),\n"
1965 "uniform float4 UserVec3 : register(c39),\n"
1966 "uniform float4 UserVec4 : register(c40),\n"
1967 "uniform float ClientTime : register(c2),\n"
1968 "uniform float2 PixelSize : register(c25),\n"
1969 "uniform float4 BloomColorSubtract : register(c43),\n"
1970 "out float4 gl_FragColor : COLOR\n"
1971 ")\n"
1972 "{\n"
1973 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1974 "#ifdef USEBLOOM\n"
1975 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1976 "#endif\n"
1977 "#ifdef USEVIEWTINT\n"
1978 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1979 "#endif\n"
1980 "\n"
1981 "#ifdef USEPOSTPROCESSING\n"
1982 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1983 "// 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"
1984 "       float sobel = 1.0;\n"
1985 "       // float2 ts = textureSize(Texture_First, 0);\n"
1986 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
1987 "       float2 px = PixelSize;\n"
1988 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1989 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
1990 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1991 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1992 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
1993 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1994 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1995 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
1996 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1997 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1998 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
1999 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2000 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2001 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2002 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2003 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2004 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2005 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2006 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2007 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2008 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2009 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2010 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2011 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2012 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2013 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2014 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2015 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2016 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2017 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2018 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2019 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2020 "#endif\n"
2021 "\n"
2022 "#ifdef USESATURATION\n"
2023 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2024 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2025 "       // 'vampire sight' effect, wheres red is compensated\n"
2026 "       #ifdef SATURATION_REDCOMPENSATE\n"
2027 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2028 "               gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2029 "               gl_FragColor.r += r;\n"
2030 "       #else\n"
2031 "               // normal desaturation\n"
2032 "               //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2033 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2034 "       #endif\n"
2035 "#endif\n"
2036 "\n"
2037 "#ifdef USEGAMMARAMPS\n"
2038 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2039 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2040 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2041 "#endif\n"
2042 "}\n"
2043 "#endif\n"
2044 "#else // !MODE_POSTPROCESS\n"
2045 "\n"
2046 "\n"
2047 "\n"
2048 "\n"
2049 "#ifdef MODE_GENERIC\n"
2050 "#ifdef VERTEX_SHADER\n"
2051 "void main\n"
2052 "(\n"
2053 "float4 gl_Vertex : POSITION,\n"
2054 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2055 "float4 gl_Color : COLOR0,\n"
2056 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2057 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2058 "out float4 gl_Position : POSITION,\n"
2059 "#ifdef USEDIFFUSE\n"
2060 "out float2 TexCoord1 : TEXCOORD0,\n"
2061 "#endif\n"
2062 "#ifdef USESPECULAR\n"
2063 "out float2 TexCoord2 : TEXCOORD1,\n"
2064 "#endif\n"
2065 "out float4 gl_FrontColor : COLOR\n"
2066 ")\n"
2067 "{\n"
2068 "#ifdef HLSL\n"
2069 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2070 "#else\n"
2071 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2072 "#endif\n"
2073 "#ifdef USEDIFFUSE\n"
2074 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2075 "#endif\n"
2076 "#ifdef USESPECULAR\n"
2077 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2078 "#endif\n"
2079 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2080 "}\n"
2081 "#endif\n"
2082 "\n"
2083 "#ifdef FRAGMENT_SHADER\n"
2084 "\n"
2085 "void main\n"
2086 "(\n"
2087 "float4 gl_FrontColor : COLOR0,\n"
2088 "float2 TexCoord1 : TEXCOORD0,\n"
2089 "float2 TexCoord2 : TEXCOORD1,\n"
2090 "#ifdef USEDIFFUSE\n"
2091 "uniform sampler Texture_First : register(s0),\n"
2092 "#endif\n"
2093 "#ifdef USESPECULAR\n"
2094 "uniform sampler Texture_Second : register(s1),\n"
2095 "#endif\n"
2096 "out float4 gl_FragColor : COLOR\n"
2097 ")\n"
2098 "{\n"
2099 "#ifdef USEVIEWTINT\n"
2100 "       gl_FragColor = gl_FrontColor;\n"
2101 "#else\n"
2102 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2103 "#endif\n"
2104 "#ifdef USEDIFFUSE\n"
2105 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2106 "#endif\n"
2107 "\n"
2108 "#ifdef USESPECULAR\n"
2109 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2110 "# ifdef USECOLORMAPPING\n"
2111 "       gl_FragColor *= tex2;\n"
2112 "# endif\n"
2113 "# ifdef USEGLOW\n"
2114 "       gl_FragColor += tex2;\n"
2115 "# endif\n"
2116 "# ifdef USEVERTEXTEXTUREBLEND\n"
2117 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2118 "# endif\n"
2119 "#endif\n"
2120 "}\n"
2121 "#endif\n"
2122 "#else // !MODE_GENERIC\n"
2123 "\n"
2124 "\n"
2125 "\n"
2126 "\n"
2127 "#ifdef MODE_BLOOMBLUR\n"
2128 "#ifdef VERTEX_SHADER\n"
2129 "void main\n"
2130 "(\n"
2131 "float4 gl_Vertex : POSITION,\n"
2132 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2133 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2134 "out float4 gl_Position : POSITION,\n"
2135 "out float2 TexCoord : TEXCOORD0\n"
2136 ")\n"
2137 "{\n"
2138 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2139 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2140 "}\n"
2141 "#endif\n"
2142 "\n"
2143 "#ifdef FRAGMENT_SHADER\n"
2144 "\n"
2145 "void main\n"
2146 "(\n"
2147 "float2 TexCoord : TEXCOORD0,\n"
2148 "uniform sampler Texture_First : register(s0),\n"
2149 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2150 "out float4 gl_FragColor : COLOR\n"
2151 ")\n"
2152 "{\n"
2153 "       int i;\n"
2154 "       float2 tc = TexCoord;\n"
2155 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2156 "       tc += BloomBlur_Parameters.xy;\n"
2157 "       for (i = 1;i < SAMPLES;i++)\n"
2158 "       {\n"
2159 "               color += tex2D(Texture_First, tc).rgb;\n"
2160 "               tc += BloomBlur_Parameters.xy;\n"
2161 "       }\n"
2162 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2163 "}\n"
2164 "#endif\n"
2165 "#else // !MODE_BLOOMBLUR\n"
2166 "#ifdef MODE_REFRACTION\n"
2167 "#ifdef VERTEX_SHADER\n"
2168 "void main\n"
2169 "(\n"
2170 "float4 gl_Vertex : POSITION,\n"
2171 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2172 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2173 "uniform float4x4 TexMatrix : register(c0),\n"
2174 "uniform float3 EyePosition : register(c24),\n"
2175 "out float4 gl_Position : POSITION,\n"
2176 "out float2 TexCoord : TEXCOORD0,\n"
2177 "out float3 EyeVector : TEXCOORD1,\n"
2178 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2179 ")\n"
2180 "{\n"
2181 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2182 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2183 "       ModelViewProjectionPosition = gl_Position;\n"
2184 "}\n"
2185 "#endif\n"
2186 "\n"
2187 "#ifdef FRAGMENT_SHADER\n"
2188 "void main\n"
2189 "(\n"
2190 "float2 TexCoord : TEXCOORD0,\n"
2191 "float3 EyeVector : TEXCOORD1,\n"
2192 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2193 "uniform sampler Texture_Normal : register(s0),\n"
2194 "uniform sampler Texture_Refraction : register(s3),\n"
2195 "uniform sampler Texture_Reflection : register(s7),\n"
2196 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2197 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2198 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2199 "uniform float4 RefractColor : register(c29),\n"
2200 "out float4 gl_FragColor : COLOR\n"
2201 ")\n"
2202 "{\n"
2203 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2204 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2205 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2206 "       float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2207 "       // FIXME temporary hack to detect the case that the reflection\n"
2208 "       // gets blackened at edges due to leaving the area that contains actual\n"
2209 "       // content.\n"
2210 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2211 "       // 'appening.\n"
2212 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2213 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2214 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2215 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2216 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2217 "       gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2218 "}\n"
2219 "#endif\n"
2220 "#else // !MODE_REFRACTION\n"
2221 "\n"
2222 "\n"
2223 "\n"
2224 "\n"
2225 "#ifdef MODE_WATER\n"
2226 "#ifdef VERTEX_SHADER\n"
2227 "\n"
2228 "void main\n"
2229 "(\n"
2230 "float4 gl_Vertex : POSITION,\n"
2231 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2232 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2233 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2234 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2235 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2236 "uniform float4x4 TexMatrix : register(c0),\n"
2237 "uniform float3 EyePosition : register(c24),\n"
2238 "out float4 gl_Position : POSITION,\n"
2239 "out float2 TexCoord : TEXCOORD0,\n"
2240 "out float3 EyeVector : TEXCOORD1,\n"
2241 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2242 ")\n"
2243 "{\n"
2244 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2245 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2246 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2247 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2248 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2249 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2250 "       ModelViewProjectionPosition = gl_Position;\n"
2251 "}\n"
2252 "#endif\n"
2253 "\n"
2254 "#ifdef FRAGMENT_SHADER\n"
2255 "void main\n"
2256 "(\n"
2257 "float2 TexCoord : TEXCOORD0,\n"
2258 "float3 EyeVector : TEXCOORD1,\n"
2259 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2260 "uniform sampler Texture_Normal : register(s0),\n"
2261 "uniform sampler Texture_Refraction : register(s3),\n"
2262 "uniform sampler Texture_Reflection : register(s7),\n"
2263 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2264 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2265 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2266 "uniform float4 RefractColor : register(c29),\n"
2267 "uniform float4 ReflectColor : register(c26),\n"
2268 "uniform float ReflectFactor : register(c27),\n"
2269 "uniform float ReflectOffset : register(c28),\n"
2270 "out float4 gl_FragColor : COLOR\n"
2271 ")\n"
2272 "{\n"
2273 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2274 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2275 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2276 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2277 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2278 "       // FIXME temporary hack to detect the case that the reflection\n"
2279 "       // gets blackened at edges due to leaving the area that contains actual\n"
2280 "       // content.\n"
2281 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2282 "       // 'appening.\n"
2283 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2284 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2285 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2286 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2287 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2288 "       f  = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2289 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2290 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2291 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2292 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2293 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2294 "       gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2295 "}\n"
2296 "#endif\n"
2297 "#else // !MODE_WATER\n"
2298 "\n"
2299 "\n"
2300 "\n"
2301 "\n"
2302 "// 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"
2303 "\n"
2304 "// fragment shader specific:\n"
2305 "#ifdef FRAGMENT_SHADER\n"
2306 "\n"
2307 "#ifdef USEFOG\n"
2308 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2309 "{\n"
2310 "       float fogfrac;\n"
2311 "#ifdef USEFOGHEIGHTTEXTURE\n"
2312 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2313 "       fogfrac = fogheightpixel.a;\n"
2314 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2315 "#else\n"
2316 "# ifdef USEFOGOUTSIDE\n"
2317 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2318 "# else\n"
2319 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2320 "# endif\n"
2321 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2322 "#endif\n"
2323 "}\n"
2324 "#endif\n"
2325 "\n"
2326 "#ifdef USEOFFSETMAPPING\n"
2327 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2328 "{\n"
2329 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2330 "       // 14 sample relief mapping: linear search and then binary search\n"
2331 "       // this basically steps forward a small amount repeatedly until it finds\n"
2332 "       // itself inside solid, then jitters forward and back using decreasing\n"
2333 "       // amounts to find the impact\n"
2334 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2335 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2336 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2337 "       float3 RT = float3(TexCoord, 1);\n"
2338 "       OffsetVector *= 0.1;\n"
2339 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2340 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2341 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2342 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\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)          - 0.5);\n"
2349 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2350 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2351 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2352 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2353 "       return RT.xy;\n"
2354 "#else\n"
2355 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2356 "       // this basically moves forward the full distance, and then backs up based\n"
2357 "       // on height of samples\n"
2358 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2359 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2360 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2361 "       TexCoord += OffsetVector;\n"
2362 "       OffsetVector *= 0.333;\n"
2363 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2364 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2365 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2366 "       return TexCoord;\n"
2367 "#endif\n"
2368 "}\n"
2369 "#endif // USEOFFSETMAPPING\n"
2370 "\n"
2371 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2372 "#if defined(USESHADOWMAP2D)\n"
2373 "# ifdef USESHADOWMAPORTHO\n"
2374 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2375 "# else\n"
2376 "#  ifdef USESHADOWMAPVSDCT\n"
2377 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2378 "{\n"
2379 "       float3 adir = abs(dir);\n"
2380 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2381 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2382 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2383 "}\n"
2384 "#  else\n"
2385 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2386 "{\n"
2387 "       float3 adir = abs(dir);\n"
2388 "       float ma = adir.z;\n"
2389 "       float4 proj = float4(dir, 2.5);\n"
2390 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2391 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2392 "#ifdef HLSL\n"
2393 "       return float3(proj.xy * ShadowMap_Parameters.x / ma + float2(0.5,0.5) + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, ma + 64 * ShadowMap_Parameters.w);\n"
2394 "#else\n"
2395 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2396 "       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"
2397 "#endif\n"
2398 "}\n"
2399 "#  endif\n"
2400 "# endif\n"
2401 "#endif // defined(USESHADOWMAP2D)\n"
2402 "\n"
2403 "# ifdef USESHADOWMAP2D\n"
2404 "#ifdef USESHADOWMAPVSDCT\n"
2405 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2406 "#else\n"
2407 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2408 "#endif\n"
2409 "{\n"
2410 "#ifdef USESHADOWMAPVSDCT\n"
2411 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2412 "#else\n"
2413 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2414 "#endif\n"
2415 "       float f;\n"
2416 "\n"
2417 "#  ifdef USESHADOWSAMPLER\n"
2418 "#    ifdef USESHADOWMAPPCF\n"
2419 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2420 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2421 "       f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2422 "#    else\n"
2423 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2424 "#    endif\n"
2425 "#  else\n"
2426 "#    ifdef USESHADOWMAPPCF\n"
2427 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2428 "#      ifdef GL_ARB_texture_gather\n"
2429 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2430 "#      else\n"
2431 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2432 "#      endif\n"
2433 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2434 "#      if USESHADOWMAPPCF > 1\n"
2435 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2436 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2437 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2438 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2439 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2440 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2441 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2442 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2443 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2444 "       float4 locols = float4(group1.ab, group3.ab);\n"
2445 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2446 "       locols.yz += group2.ab;\n"
2447 "       hicols.yz += group8.rg;\n"
2448 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2449 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2450 "                               lerp(locols, hicols, offset.y);\n"
2451 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2452 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2453 "       f = dot(cols, float4(1.0/25.0));\n"
2454 "#      else\n"
2455 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2456 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2457 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2458 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2459 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2460 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2461 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2462 "#      endif\n"
2463 "#     else\n"
2464 "#      ifdef GL_EXT_gpu_shader4\n"
2465 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2466 "#      else\n"
2467 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2468 "#      endif\n"
2469 "#      if USESHADOWMAPPCF > 1\n"
2470 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2471 "       center *= ShadowMap_TextureScale;\n"
2472 "       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"
2473 "       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"
2474 "       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"
2475 "       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"
2476 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2477 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2478 "#      else\n"
2479 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2480 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2481 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2482 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2483 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2484 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2485 "#      endif\n"
2486 "#     endif\n"
2487 "#    else\n"
2488 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2489 "#    endif\n"
2490 "#  endif\n"
2491 "#  ifdef USESHADOWMAPORTHO\n"
2492 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2493 "#  else\n"
2494 "       return f;\n"
2495 "#  endif\n"
2496 "}\n"
2497 "# endif\n"
2498 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2499 "#endif // FRAGMENT_SHADER\n"
2500 "\n"
2501 "\n"
2502 "\n"
2503 "\n"
2504 "#ifdef MODE_DEFERREDGEOMETRY\n"
2505 "#ifdef VERTEX_SHADER\n"
2506 "void main\n"
2507 "(\n"
2508 "float4 gl_Vertex : POSITION,\n"
2509 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2510 "#ifdef USEVERTEXTEXTUREBLEND\n"
2511 "float4 gl_Color : COLOR0,\n"
2512 "#endif\n"
2513 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2514 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2515 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2516 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2517 "uniform float4x4 TexMatrix : register(c0),\n"
2518 "#ifdef USEVERTEXTEXTUREBLEND\n"
2519 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2520 "#endif\n"
2521 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2522 "#ifdef USEOFFSETMAPPING\n"
2523 "uniform float3 EyePosition : register(c24),\n"
2524 "#endif\n"
2525 "out float4 gl_Position : POSITION,\n"
2526 "#ifdef USEVERTEXTEXTUREBLEND\n"
2527 "out float4 gl_FrontColor : COLOR,\n"
2528 "#endif\n"
2529 "out float4 TexCoordBoth : TEXCOORD0,\n"
2530 "#ifdef USEOFFSETMAPPING\n"
2531 "out float3 EyeVector : TEXCOORD2,\n"
2532 "#endif\n"
2533 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2534 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2535 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2536 ")\n"
2537 "{\n"
2538 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2539 "#ifdef USEVERTEXTEXTUREBLEND\n"
2540 "#ifdef HLSL\n"
2541 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2542 "#else\n"
2543 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2544 "#endif\n"
2545 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2546 "#endif\n"
2547 "\n"
2548 "       // transform unnormalized eye direction into tangent space\n"
2549 "#ifdef USEOFFSETMAPPING\n"
2550 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2551 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2552 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2553 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2554 "#endif\n"
2555 "\n"
2556 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2557 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2558 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2559 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2560 "       VectorR.w = gl_Position.z;\n"
2561 "}\n"
2562 "#endif // VERTEX_SHADER\n"
2563 "\n"
2564 "#ifdef FRAGMENT_SHADER\n"
2565 "void main\n"
2566 "(\n"
2567 "float4 TexCoordBoth : TEXCOORD0,\n"
2568 "float3 EyeVector : TEXCOORD2,\n"
2569 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2570 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2571 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2572 "uniform sampler Texture_Normal : register(s0),\n"
2573 "#ifdef USEALPHAKILL\n"
2574 "uniform sampler Texture_Color : register(s1),\n"
2575 "#endif\n"
2576 "uniform sampler Texture_Gloss : register(s2),\n"
2577 "#ifdef USEVERTEXTEXTUREBLEND\n"
2578 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2579 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2580 "#endif\n"
2581 "#ifdef USEOFFSETMAPPING\n"
2582 "uniform float OffsetMapping_Scale : register(c24),\n"
2583 "#endif\n"
2584 "uniform half SpecularPower : register(c36),\n"
2585 "#ifdef HLSL\n"
2586 "out float4 gl_FragData0 : COLOR0,\n"
2587 "out float4 gl_FragData1 : COLOR1\n"
2588 "#else\n"
2589 "out float4 gl_FragColor : COLOR\n"
2590 "#endif\n"
2591 ")\n"
2592 "{\n"
2593 "       float2 TexCoord = TexCoordBoth.xy;\n"
2594 "#ifdef USEOFFSETMAPPING\n"
2595 "       // apply offsetmapping\n"
2596 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2597 "#define TexCoord TexCoordOffset\n"
2598 "#endif\n"
2599 "\n"
2600 "#ifdef USEALPHAKILL\n"
2601 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2602 "               discard;\n"
2603 "#endif\n"
2604 "\n"
2605 "#ifdef USEVERTEXTEXTUREBLEND\n"
2606 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2607 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2608 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2609 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2610 "#endif\n"
2611 "\n"
2612 "#ifdef USEVERTEXTEXTUREBLEND\n"
2613 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2614 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2615 "#else\n"
2616 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2617 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2618 "#endif\n"
2619 "\n"
2620 "#ifdef HLSL\n"
2621 "       gl_FragData0 = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR.xyz) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2622 "       float Depth = VectorR.w / 256.0;\n"
2623 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2624 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2625 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2626 "       gl_FragData1 = depthcolor;\n"
2627 "#else\n"
2628 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2629 "#endif\n"
2630 "}\n"
2631 "#endif // FRAGMENT_SHADER\n"
2632 "#else // !MODE_DEFERREDGEOMETRY\n"
2633 "\n"
2634 "\n"
2635 "\n"
2636 "\n"
2637 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2638 "#ifdef VERTEX_SHADER\n"
2639 "void main\n"
2640 "(\n"
2641 "float4 gl_Vertex : POSITION,\n"
2642 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2643 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2644 "out float4 gl_Position : POSITION,\n"
2645 "out float4 ModelViewPosition : TEXCOORD0\n"
2646 ")\n"
2647 "{\n"
2648 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2649 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2650 "}\n"
2651 "#endif // VERTEX_SHADER\n"
2652 "\n"
2653 "#ifdef FRAGMENT_SHADER\n"
2654 "void main\n"
2655 "(\n"
2656 "#ifdef HLSL\n"
2657 "float2 Pixel : VPOS,\n"
2658 "#else\n"
2659 "float2 Pixel : WPOS,\n"
2660 "#endif\n"
2661 "float4 ModelViewPosition : TEXCOORD0,\n"
2662 "uniform float4x4 ViewToLight : register(c44),\n"
2663 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2664 "uniform float3 LightPosition : register(c23),\n"
2665 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2666 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2667 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2668 "#ifdef USESPECULAR\n"
2669 "uniform half3 DeferredColor_Specular : register(c11),\n"
2670 "uniform half SpecularPower : register(c36),\n"
2671 "#endif\n"
2672 "uniform sampler Texture_Attenuation : register(s9),\n"
2673 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2674 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2675 "\n"
2676 "#ifdef USECUBEFILTER\n"
2677 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2678 "#endif\n"
2679 "\n"
2680 "#ifdef USESHADOWMAP2D\n"
2681 "# ifdef USESHADOWSAMPLER\n"
2682 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2683 "# else\n"
2684 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2685 "# endif\n"
2686 "#endif\n"
2687 "\n"
2688 "#ifdef USESHADOWMAPVSDCT\n"
2689 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2690 "#endif\n"
2691 "\n"
2692 "#if defined(USESHADOWMAP2D)\n"
2693 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2694 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2695 "#endif\n"
2696 "\n"
2697 "out float4 gl_FragData0 : COLOR0,\n"
2698 "out float4 gl_FragData1 : COLOR1\n"
2699 ")\n"
2700 "{\n"
2701 "       // calculate viewspace pixel position\n"
2702 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2703 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2704 "       float3 position;\n"
2705 "#ifdef HLSL\n"
2706 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2707 "#else\n"
2708 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2709 "#endif\n"
2710 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2711 "       // decode viewspace pixel normal\n"
2712 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2713 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2714 "       // surfacenormal = pixel normal in viewspace\n"
2715 "       // LightVector = pixel to light in viewspace\n"
2716 "       // CubeVector = position in lightspace\n"
2717 "       // eyevector = pixel to view in viewspace\n"
2718 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2719 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2720 "#ifdef USEDIFFUSE\n"
2721 "       // calculate diffuse shading\n"
2722 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2723 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2724 "#endif\n"
2725 "#ifdef USESPECULAR\n"
2726 "       // calculate directional shading\n"
2727 "       float3 eyevector = position * -1.0;\n"
2728 "#  ifdef USEEXACTSPECULARMATH\n"
2729 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2730 "#  else\n"
2731 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2732 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2733 "#  endif\n"
2734 "#endif\n"
2735 "\n"
2736 "#if defined(USESHADOWMAP2D)\n"
2737 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2738 "#ifdef USESHADOWMAPVSDCT\n"
2739 ", Texture_CubeProjection\n"
2740 "#endif\n"
2741 "       ));\n"
2742 "#endif\n"
2743 "\n"
2744 "#ifdef USEDIFFUSE\n"
2745 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2746 "#else\n"
2747 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2748 "#endif\n"
2749 "#ifdef USESPECULAR\n"
2750 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2751 "#else\n"
2752 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2753 "#endif\n"
2754 "\n"
2755 "# ifdef USECUBEFILTER\n"
2756 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2757 "       gl_FragData0.rgb *= cubecolor;\n"
2758 "       gl_FragData1.rgb *= cubecolor;\n"
2759 "# endif\n"
2760 "}\n"
2761 "#endif // FRAGMENT_SHADER\n"
2762 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2763 "\n"
2764 "\n"
2765 "\n"
2766 "\n"
2767 "#ifdef VERTEX_SHADER\n"
2768 "void main\n"
2769 "(\n"
2770 "float4 gl_Vertex : POSITION,\n"
2771 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2772 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2773 "float4 gl_Color : COLOR0,\n"
2774 "#endif\n"
2775 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2776 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2777 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2778 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2779 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2780 "\n"
2781 "uniform float3 EyePosition : register(c24),\n"
2782 "uniform float4x4 TexMatrix : register(c0),\n"
2783 "#ifdef USEVERTEXTEXTUREBLEND\n"
2784 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2785 "#endif\n"
2786 "#ifdef MODE_LIGHTSOURCE\n"
2787 "uniform float4x4 ModelToLight : register(c20),\n"
2788 "#endif\n"
2789 "#ifdef MODE_LIGHTSOURCE\n"
2790 "uniform float3 LightPosition : register(c27),\n"
2791 "#endif\n"
2792 "#ifdef MODE_LIGHTDIRECTION\n"
2793 "uniform float3 LightDir : register(c26),\n"
2794 "#endif\n"
2795 "uniform float4 FogPlane : register(c25),\n"
2796 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2797 "uniform float3 LightPosition : register(c27),\n"
2798 "#endif\n"
2799 "#ifdef USESHADOWMAPORTHO\n"
2800 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2801 "#endif\n"
2802 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2803 "out float4 gl_FrontColor : COLOR,\n"
2804 "#endif\n"
2805 "out float4 TexCoordBoth : TEXCOORD0,\n"
2806 "#ifdef USELIGHTMAP\n"
2807 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2808 "#endif\n"
2809 "#ifdef USEEYEVECTOR\n"
2810 "out float3 EyeVector : TEXCOORD2,\n"
2811 "#endif\n"
2812 "#ifdef USEREFLECTION\n"
2813 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2814 "#endif\n"
2815 "#ifdef USEFOG\n"
2816 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2817 "#endif\n"
2818 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2819 "out float3 LightVector : TEXCOORD1,\n"
2820 "#endif\n"
2821 "#ifdef MODE_LIGHTSOURCE\n"
2822 "out float3 CubeVector : TEXCOORD3,\n"
2823 "#endif\n"
2824 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2825 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2826 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2827 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2828 "#endif\n"
2829 "#ifdef USESHADOWMAPORTHO\n"
2830 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2831 "#endif\n"
2832 "out float4 gl_Position : POSITION\n"
2833 ")\n"
2834 "{\n"
2835 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2836 "#ifdef HLSL\n"
2837 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2838 "#else\n"
2839 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2840 "#endif\n"
2841 "#endif\n"
2842 "       // copy the surface texcoord\n"
2843 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2844 "#ifdef USEVERTEXTEXTUREBLEND\n"
2845 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2846 "#endif\n"
2847 "#ifdef USELIGHTMAP\n"
2848 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2849 "#endif\n"
2850 "\n"
2851 "#ifdef MODE_LIGHTSOURCE\n"
2852 "       // transform vertex position into light attenuation/cubemap space\n"
2853 "       // (-1 to +1 across the light box)\n"
2854 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2855 "\n"
2856 "# ifdef USEDIFFUSE\n"
2857 "       // transform unnormalized light direction into tangent space\n"
2858 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2859 "       //  normalize it per pixel)\n"
2860 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2861 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2862 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2863 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2864 "# endif\n"
2865 "#endif\n"
2866 "\n"
2867 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2868 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2869 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2870 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2871 "#endif\n"
2872 "\n"
2873 "       // transform unnormalized eye direction into tangent space\n"
2874 "#ifdef USEEYEVECTOR\n"
2875 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2876 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2877 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2878 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2879 "#endif\n"
2880 "\n"
2881 "#ifdef USEFOG\n"
2882 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2883 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2884 "#endif\n"
2885 "\n"
2886 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2887 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2888 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2889 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2890 "#endif\n"
2891 "\n"
2892 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2893 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2894 "\n"
2895 "#ifdef USESHADOWMAPORTHO\n"
2896 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2897 "#endif\n"
2898 "\n"
2899 "#ifdef USEREFLECTION\n"
2900 "       ModelViewProjectionPosition = gl_Position;\n"
2901 "#endif\n"
2902 "}\n"
2903 "#endif // VERTEX_SHADER\n"
2904 "\n"
2905 "\n"
2906 "\n"
2907 "\n"
2908 "#ifdef FRAGMENT_SHADER\n"
2909 "void main\n"
2910 "(\n"
2911 "#ifdef USEDEFERREDLIGHTMAP\n"
2912 "#ifdef HLSL\n"
2913 "float2 Pixel : VPOS,\n"
2914 "#else\n"
2915 "float2 Pixel : WPOS,\n"
2916 "#endif\n"
2917 "#endif\n"
2918 "float4 gl_FrontColor : COLOR,\n"
2919 "float4 TexCoordBoth : TEXCOORD0,\n"
2920 "#ifdef USELIGHTMAP\n"
2921 "float2 TexCoordLightmap : TEXCOORD1,\n"
2922 "#endif\n"
2923 "#ifdef USEEYEVECTOR\n"
2924 "float3 EyeVector : TEXCOORD2,\n"
2925 "#endif\n"
2926 "#ifdef USEREFLECTION\n"
2927 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2928 "#endif\n"
2929 "#ifdef USEFOG\n"
2930 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2931 "#endif\n"
2932 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2933 "float3 LightVector : TEXCOORD1,\n"
2934 "#endif\n"
2935 "#ifdef MODE_LIGHTSOURCE\n"
2936 "float3 CubeVector : TEXCOORD3,\n"
2937 "#endif\n"
2938 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2939 "float4 ModelViewPosition : TEXCOORD0,\n"
2940 "#endif\n"
2941 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2942 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2943 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2944 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2945 "#endif\n"
2946 "#ifdef USESHADOWMAPORTHO\n"
2947 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2948 "#endif\n"
2949 "\n"
2950 "uniform sampler Texture_Normal : register(s0),\n"
2951 "uniform sampler Texture_Color : register(s1),\n"
2952 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2953 "uniform sampler Texture_Gloss : register(s2),\n"
2954 "#endif\n"
2955 "#ifdef USEGLOW\n"
2956 "uniform sampler Texture_Glow : register(s3),\n"
2957 "#endif\n"
2958 "#ifdef USEVERTEXTEXTUREBLEND\n"
2959 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2960 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2961 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2962 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2963 "#endif\n"
2964 "#ifdef USEGLOW\n"
2965 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2966 "#endif\n"
2967 "#endif\n"
2968 "#ifdef USECOLORMAPPING\n"
2969 "uniform sampler Texture_Pants : register(s4),\n"
2970 "uniform sampler Texture_Shirt : register(s7),\n"
2971 "#endif\n"
2972 "#ifdef USEFOG\n"
2973 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2974 "uniform sampler Texture_FogMask : register(s8),\n"
2975 "#endif\n"
2976 "#ifdef USELIGHTMAP\n"
2977 "uniform sampler Texture_Lightmap : register(s9),\n"
2978 "#endif\n"
2979 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2980 "uniform sampler Texture_Deluxemap : register(s10),\n"
2981 "#endif\n"
2982 "#ifdef USEREFLECTION\n"
2983 "uniform sampler Texture_Reflection : register(s7),\n"
2984 "#endif\n"
2985 "\n"
2986 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2987 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2988 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2989 "#endif\n"
2990 "#ifdef USEDEFERREDLIGHTMAP\n"
2991 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2992 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2993 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2994 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2995 "#endif\n"
2996 "\n"
2997 "#ifdef USECOLORMAPPING\n"
2998 "uniform half3 Color_Pants : register(c7),\n"
2999 "uniform half3 Color_Shirt : register(c8),\n"
3000 "#endif\n"
3001 "#ifdef USEFOG\n"
3002 "uniform float3 FogColor : register(c16),\n"
3003 "uniform float FogRangeRecip : register(c20),\n"
3004 "uniform float FogPlaneViewDist : register(c19),\n"
3005 "uniform float FogHeightFade : register(c17),\n"
3006 "#endif\n"
3007 "\n"
3008 "#ifdef USEOFFSETMAPPING\n"
3009 "uniform float OffsetMapping_Scale : register(c24),\n"
3010 "#endif\n"
3011 "\n"
3012 "#ifdef USEDEFERREDLIGHTMAP\n"
3013 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3014 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3015 "uniform half3 DeferredMod_Specular : register(c13),\n"
3016 "#endif\n"
3017 "uniform half3 Color_Ambient : register(c3),\n"
3018 "uniform half3 Color_Diffuse : register(c4),\n"
3019 "uniform half3 Color_Specular : register(c5),\n"
3020 "uniform half SpecularPower : register(c36),\n"
3021 "#ifdef USEGLOW\n"
3022 "uniform half3 Color_Glow : register(c6),\n"
3023 "#endif\n"
3024 "uniform half Alpha : register(c0),\n"
3025 "#ifdef USEREFLECTION\n"
3026 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3027 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3028 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3029 "uniform half4 ReflectColor : register(c26),\n"
3030 "#endif\n"
3031 "#ifdef USEREFLECTCUBE\n"
3032 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3033 "uniform sampler Texture_ReflectMask : register(s5),\n"
3034 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3035 "#endif\n"
3036 "#ifdef MODE_LIGHTDIRECTION\n"
3037 "uniform half3 LightColor : register(c21),\n"
3038 "#endif\n"
3039 "#ifdef MODE_LIGHTSOURCE\n"
3040 "uniform half3 LightColor : register(c21),\n"
3041 "#endif\n"
3042 "\n"
3043 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3044 "uniform sampler Texture_Attenuation : register(s9),\n"
3045 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3046 "#endif\n"
3047 "\n"
3048 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3049 "\n"
3050 "#ifdef USESHADOWMAP2D\n"
3051 "# ifdef USESHADOWSAMPLER\n"
3052 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3053 "# else\n"
3054 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3055 "# endif\n"
3056 "#endif\n"
3057 "\n"
3058 "#ifdef USESHADOWMAPVSDCT\n"
3059 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3060 "#endif\n"
3061 "\n"
3062 "#if defined(USESHADOWMAP2D)\n"
3063 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3064 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3065 "#endif\n"
3066 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3067 "\n"
3068 "out float4 gl_FragColor : COLOR\n"
3069 ")\n"
3070 "{\n"
3071 "       float2 TexCoord = TexCoordBoth.xy;\n"
3072 "#ifdef USEVERTEXTEXTUREBLEND\n"
3073 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3074 "#endif\n"
3075 "#ifdef USEOFFSETMAPPING\n"
3076 "       // apply offsetmapping\n"
3077 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3078 "#define TexCoord TexCoordOffset\n"
3079 "#endif\n"
3080 "\n"
3081 "       // combine the diffuse textures (base, pants, shirt)\n"
3082 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3083 "#ifdef USEALPHAKILL\n"
3084 "       if (color.a < 0.5)\n"
3085 "               discard;\n"
3086 "#endif\n"
3087 "       color.a *= Alpha;\n"
3088 "#ifdef USECOLORMAPPING\n"
3089 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3090 "#endif\n"
3091 "#ifdef USEVERTEXTEXTUREBLEND\n"
3092 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3093 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3094 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3095 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3096 "       color.a = 1.0;\n"
3097 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3098 "#endif\n"
3099 "\n"
3100 "       // get the surface normal\n"
3101 "#ifdef USEVERTEXTEXTUREBLEND\n"
3102 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3103 "#else\n"
3104 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3105 "#endif\n"
3106 "\n"
3107 "       // get the material colors\n"
3108 "       half3 diffusetex = color.rgb;\n"
3109 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3110 "# ifdef USEVERTEXTEXTUREBLEND\n"
3111 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3112 "# else\n"
3113 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3114 "# endif\n"
3115 "#endif\n"
3116 "\n"
3117 "#ifdef USEREFLECTCUBE\n"
3118 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3119 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3120 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3121 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3122 "#endif\n"
3123 "\n"
3124 "\n"
3125 "\n"
3126 "\n"
3127 "#ifdef MODE_LIGHTSOURCE\n"
3128 "       // light source\n"
3129 "#ifdef USEDIFFUSE\n"
3130 "       half3 lightnormal = half3(normalize(LightVector));\n"
3131 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3132 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3133 "#ifdef USESPECULAR\n"
3134 "#ifdef USEEXACTSPECULARMATH\n"
3135 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3136 "#else\n"
3137 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3138 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3139 "#endif\n"
3140 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3141 "#endif\n"
3142 "#else\n"
3143 "       color.rgb = diffusetex * Color_Ambient;\n"
3144 "#endif\n"
3145 "       color.rgb *= LightColor;\n"
3146 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3147 "#if defined(USESHADOWMAP2D)\n"
3148 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3149 "#ifdef USESHADOWMAPVSDCT\n"
3150 ", Texture_CubeProjection\n"
3151 "#endif\n"
3152 "       ));\n"
3153 "\n"
3154 "#endif\n"
3155 "# ifdef USECUBEFILTER\n"
3156 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3157 "# endif\n"
3158 "\n"
3159 "#ifdef USESHADOWMAP2D\n"
3160 "#ifdef USESHADOWMAPVSDCT\n"
3161 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3162 "#else\n"
3163 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3164 "#endif\n"
3165 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3166 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3167 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3168 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3169 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3170 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3171 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3172 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3173 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3174 "//     color.r = half(shadowmaptc.z);\n"
3175 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3176 "//     color.r = half(shadowmaptc.z);\n"
3177 "//     color.r = 1;\n"
3178 "//     color.rgb = abs(CubeVector);\n"
3179 "#endif\n"
3180 "//     color.rgb = half3(1,1,1);\n"
3181 "#endif // MODE_LIGHTSOURCE\n"
3182 "\n"
3183 "\n"
3184 "\n"
3185 "\n"
3186 "#ifdef MODE_LIGHTDIRECTION\n"
3187 "#define SHADING\n"
3188 "#ifdef USEDIFFUSE\n"
3189 "       half3 lightnormal = half3(normalize(LightVector));\n"
3190 "#endif\n"
3191 "#define lightcolor LightColor\n"
3192 "#endif // MODE_LIGHTDIRECTION\n"
3193 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3194 "#define SHADING\n"
3195 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3196 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3197 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3198 "       // convert modelspace light vector to tangentspace\n"
3199 "       half3 lightnormal;\n"
3200 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3201 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3202 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3203 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3204 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3205 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3206 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3207 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3208 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3209 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3210 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3211 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3212 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3213 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3214 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3215 "#define SHADING\n"
3216 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3217 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3218 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3219 "#endif\n"
3220 "\n"
3221 "\n"
3222 "\n"
3223 "\n"
3224 "#ifdef MODE_FAKELIGHT\n"
3225 "#define SHADING\n"
3226 "half3 lightnormal = half3(normalize(EyeVector));\n"
3227 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3228 "#endif // MODE_FAKELIGHT\n"
3229 "\n"
3230 "\n"
3231 "\n"
3232 "\n"
3233 "#ifdef MODE_LIGHTMAP\n"
3234 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3235 "#endif // MODE_LIGHTMAP\n"
3236 "#ifdef MODE_VERTEXCOLOR\n"
3237 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3238 "#endif // MODE_VERTEXCOLOR\n"
3239 "#ifdef MODE_FLATCOLOR\n"
3240 "       color.rgb = diffusetex * Color_Ambient;\n"
3241 "#endif // MODE_FLATCOLOR\n"
3242 "\n"
3243 "\n"
3244 "\n"
3245 "\n"
3246 "#ifdef SHADING\n"
3247 "# ifdef USEDIFFUSE\n"
3248 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3249 "#  ifdef USESPECULAR\n"
3250 "#   ifdef USEEXACTSPECULARMATH\n"
3251 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3252 "#   else\n"
3253 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3254 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3255 "#   endif\n"
3256 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3257 "#  else\n"
3258 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3259 "#  endif\n"
3260 "# else\n"
3261 "       color.rgb = diffusetex * Color_Ambient;\n"
3262 "# endif\n"
3263 "#endif\n"
3264 "\n"
3265 "#ifdef USESHADOWMAPORTHO\n"
3266 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3267 "#endif\n"
3268 "\n"
3269 "#ifdef USEDEFERREDLIGHTMAP\n"
3270 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3271 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3272 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3273 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3274 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3275 "#endif\n"
3276 "\n"
3277 "#ifdef USEGLOW\n"
3278 "#ifdef USEVERTEXTEXTUREBLEND\n"
3279 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3280 "#else\n"
3281 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3282 "#endif\n"
3283 "#endif\n"
3284 "\n"
3285 "#ifdef USEFOG\n"
3286 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3287 "#endif\n"
3288 "\n"
3289 "       // 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"
3290 "#ifdef USEREFLECTION\n"
3291 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3292 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3293 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3294 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3295 "       // FIXME temporary hack to detect the case that the reflection\n"
3296 "       // gets blackened at edges due to leaving the area that contains actual\n"
3297 "       // content.\n"
3298 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3299 "       // 'appening.\n"
3300 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3301 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3302 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3303 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3304 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3305 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3306 "#endif\n"
3307 "\n"
3308 "       gl_FragColor = float4(color);\n"
3309 "}\n"
3310 "#endif // FRAGMENT_SHADER\n"
3311 "\n"
3312 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3313 "#endif // !MODE_DEFERREDGEOMETRY\n"
3314 "#endif // !MODE_WATER\n"
3315 "#endif // !MODE_REFRACTION\n"
3316 "#endif // !MODE_BLOOMBLUR\n"
3317 "#endif // !MODE_GENERIC\n"
3318 "#endif // !MODE_POSTPROCESS\n"
3319 "#endif // !MODE_SHOWDEPTH\n"
3320 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3321 ;
3322
3323 /*
3324 =========================================================================================================================================================
3325
3326
3327
3328 =========================================================================================================================================================
3329
3330
3331
3332 =========================================================================================================================================================
3333
3334
3335
3336 =========================================================================================================================================================
3337
3338
3339
3340 =========================================================================================================================================================
3341
3342
3343
3344 =========================================================================================================================================================
3345
3346
3347
3348 =========================================================================================================================================================
3349 */
3350
3351 const char *builtingles2shaderstring =
3352 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
3353 "// written by Forest 'LordHavoc' Hale\n"
3354 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
3355 "\n"
3356 "#ifdef VERTEX_SHADER\n"
3357 "attribute vec4 Attrib_Position;\n"
3358 "attribute vec4 Attrib_Color;\n"
3359 "attribute vec4 Attrib_TexCoord0;\n"
3360 "attribute vec3 Attrib_TexCoord1;\n"
3361 "attribute vec3 Attrib_TexCoord2;\n"
3362 "attribute vec3 Attrib_TexCoord3;\n"
3363 "attribute vec4 Attrib_TexCoord4;\n"
3364 "#endif\n"
3365 "varying lowp vec4 VertexColor;\n"
3366 "\n"
3367 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
3368 "# define USEFOG\n"
3369 "#endif\n"
3370 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
3371 "#define USELIGHTMAP\n"
3372 "#endif\n"
3373 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
3374 "#define USEEYEVECTOR\n"
3375 "#endif\n"
3376 "\n"
3377 "#ifdef USESHADOWMAP2D\n"
3378 "# ifdef GL_EXT_gpu_shader4\n"
3379 "#   extension GL_EXT_gpu_shader4 : enable\n"
3380 "# endif\n"
3381 "# ifdef GL_ARB_texture_gather\n"
3382 "#   extension GL_ARB_texture_gather : enable\n"
3383 "# else\n"
3384 "#   ifdef GL_AMD_texture_texture4\n"
3385 "#     extension GL_AMD_texture_texture4 : enable\n"
3386 "#   endif\n"
3387 "# endif\n"
3388 "#endif\n"
3389 "\n"
3390 "//#ifdef USESHADOWSAMPLER\n"
3391 "//# extension GL_ARB_shadow : enable\n"
3392 "//#endif\n"
3393 "\n"
3394 "//#ifdef __GLSL_CG_DATA_TYPES\n"
3395 "//# define myhalf half\n"
3396 "//# define myhalf2 half2\n"
3397 "//# define myhalf3 half3\n"
3398 "//# define myhalf4 half4\n"
3399 "//#else\n"
3400 "# define myhalf mediump float\n"
3401 "# define myhalf2 mediump vec2\n"
3402 "# define myhalf3 mediump vec3\n"
3403 "# define myhalf4 mediump vec4\n"
3404 "//#endif\n"
3405 "\n"
3406 "#ifdef VERTEX_SHADER\n"
3407 "uniform highp mat4 ModelViewProjectionMatrix;\n"
3408 "#endif\n"
3409 "\n"
3410 "#ifdef MODE_DEPTH_OR_SHADOW\n"
3411 "#ifdef VERTEX_SHADER\n"
3412 "void main(void)\n"
3413 "{\n"
3414 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
3415 "}\n"
3416 "#endif\n"
3417 "#else // !MODE_DEPTH_ORSHADOW\n"
3418 "\n"
3419 "\n"
3420 "\n"
3421 "\n"
3422 "#ifdef MODE_SHOWDEPTH\n"
3423 "#ifdef VERTEX_SHADER\n"
3424 "void main(void)\n"
3425 "{\n"
3426 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
3427 "       VertexColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
3428 "}\n"
3429 "#endif\n"
3430 "\n"
3431 "#ifdef FRAGMENT_SHADER\n"
3432 "void main(void)\n"
3433 "{\n"
3434 "       gl_FragColor = VertexColor;\n"
3435 "}\n"
3436 "#endif\n"
3437 "#else // !MODE_SHOWDEPTH\n"
3438 "\n"
3439 "\n"
3440 "\n"
3441 "\n"
3442 "#ifdef MODE_POSTPROCESS\n"
3443 "varying mediump vec2 TexCoord1;\n"
3444 "varying mediump vec2 TexCoord2;\n"
3445 "\n"
3446 "#ifdef VERTEX_SHADER\n"
3447 "void main(void)\n"
3448 "{\n"
3449 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
3450 "       TexCoord1 = Attrib_TexCoord0.xy;\n"
3451 "#ifdef USEBLOOM\n"
3452 "       TexCoord2 = Attrib_TexCoord4.xy;\n"
3453 "#endif\n"
3454 "}\n"
3455 "#endif\n"
3456 "\n"
3457 "#ifdef FRAGMENT_SHADER\n"
3458 "uniform sampler2D Texture_First;\n"
3459 "#ifdef USEBLOOM\n"
3460 "uniform sampler2D Texture_Second;\n"
3461 "uniform lowp vec4 BloomColorSubtract;\n"
3462 "#endif\n"
3463 "#ifdef USEGAMMARAMPS\n"
3464 "uniform sampler2D Texture_GammaRamps;\n"
3465 "#endif\n"
3466 "#ifdef USESATURATION\n"
3467 "uniform lowp float Saturation;\n"
3468 "#endif\n"
3469 "#ifdef USEVIEWTINT\n"
3470 "uniform lowp vec4 ViewTintColor;\n"
3471 "#endif\n"
3472 "//uncomment these if you want to use them:\n"
3473 "uniform mediump vec4 UserVec1;\n"
3474 "uniform mediump vec4 UserVec2;\n"
3475 "// uniform mediump vec4 UserVec3;\n"
3476 "// uniform mediump vec4 UserVec4;\n"
3477 "// uniform highp float ClientTime;\n"
3478 "uniform mediump vec2 PixelSize;\n"
3479 "void main(void)\n"
3480 "{\n"
3481 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
3482 "#ifdef USEBLOOM\n"
3483 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
3484 "#endif\n"
3485 "#ifdef USEVIEWTINT\n"
3486 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
3487 "#endif\n"
3488 "\n"
3489 "#ifdef USEPOSTPROCESSING\n"
3490 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
3491 "// 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"
3492 "       float sobel = 1.0;\n"
3493 "       // vec2 ts = textureSize(Texture_First, 0);\n"
3494 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
3495 "       vec2 px = PixelSize;\n"
3496 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
3497 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
3498 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
3499 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
3500 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
3501 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
3502 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
3503 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
3504 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
3505 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
3506 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
3507 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
3508 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
3509 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
3510 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
3511 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
3512 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
3513 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
3514 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
3515 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
3516 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
3517 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
3518 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
3519 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
3520 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
3521 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
3522 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
3523 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
3524 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
3525 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
3526 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
3527 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
3528 "#endif\n"
3529 "\n"
3530 "#ifdef USESATURATION\n"
3531 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
3532 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
3533 "       // 'vampire sight' effect, wheres red is compensated\n"
3534 "       #ifdef SATURATION_REDCOMPENSATE\n"
3535 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
3536 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
3537 "               gl_FragColor.r += rboost;\n"
3538 "       #else\n"
3539 "               // normal desaturation\n"
3540 "               //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
3541 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
3542 "       #endif\n"
3543 "#endif\n"
3544 "\n"
3545 "#ifdef USEGAMMARAMPS\n"
3546 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
3547 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
3548 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
3549 "#endif\n"
3550 "}\n"
3551 "#endif\n"
3552 "#else // !MODE_POSTPROCESS\n"
3553 "\n"
3554 "\n"
3555 "\n"
3556 "\n"
3557 "#ifdef MODE_GENERIC\n"
3558 "#ifdef USEDIFFUSE\n"
3559 "varying mediump vec2 TexCoord1;\n"
3560 "#endif\n"
3561 "#ifdef USESPECULAR\n"
3562 "varying mediump vec2 TexCoord2;\n"
3563 "#endif\n"
3564 "#ifdef VERTEX_SHADER\n"
3565 "void main(void)\n"
3566 "{\n"
3567 "       VertexColor = Attrib_Color;\n"
3568 "#ifdef USEDIFFUSE\n"
3569 "       TexCoord1 = Attrib_TexCoord0.xy;\n"
3570 "#endif\n"
3571 "#ifdef USESPECULAR\n"
3572 "       TexCoord2 = Attrib_TexCoord1.xy;\n"
3573 "#endif\n"
3574 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
3575 "}\n"
3576 "#endif\n"
3577 "\n"
3578 "#ifdef FRAGMENT_SHADER\n"
3579 "#ifdef USEDIFFUSE\n"
3580 "uniform sampler2D Texture_First;\n"
3581 "#endif\n"
3582 "#ifdef USESPECULAR\n"
3583 "uniform sampler2D Texture_Second;\n"
3584 "#endif\n"
3585 "\n"
3586 "void main(void)\n"
3587 "{\n"
3588 "#ifdef USEVIEWTINT\n"
3589 "       gl_FragColor = VertexColor;\n"
3590 "#else\n"
3591 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
3592 "#endif\n"
3593 "#ifdef USEDIFFUSE\n"
3594 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
3595 "#endif\n"
3596 "\n"
3597 "#ifdef USESPECULAR\n"
3598 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
3599 "# ifdef USECOLORMAPPING\n"
3600 "       gl_FragColor *= tex2;\n"
3601 "# endif\n"
3602 "# ifdef USEGLOW\n"
3603 "       gl_FragColor += tex2;\n"
3604 "# endif\n"
3605 "# ifdef USEVERTEXTEXTUREBLEND\n"
3606 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
3607 "# endif\n"
3608 "#endif\n"
3609 "}\n"
3610 "#endif\n"
3611 "#else // !MODE_GENERIC\n"
3612 "\n"
3613 "\n"
3614 "\n"
3615 "\n"
3616 "#ifdef MODE_BLOOMBLUR\n"
3617 "varying mediump vec2 TexCoord;\n"
3618 "#ifdef VERTEX_SHADER\n"
3619 "void main(void)\n"
3620 "{\n"
3621 "       VertexColor = Attrib_Color;\n"
3622 "       TexCoord = Attrib_TexCoord0.xy;\n"
3623 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
3624 "}\n"
3625 "#endif\n"
3626 "\n"
3627 "#ifdef FRAGMENT_SHADER\n"
3628 "uniform sampler2D Texture_First;\n"
3629 "uniform mediump vec4 BloomBlur_Parameters;\n"
3630 "\n"
3631 "void main(void)\n"
3632 "{\n"
3633 "       int i;\n"
3634 "       vec2 tc = TexCoord;\n"
3635 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
3636 "       tc += BloomBlur_Parameters.xy;\n"
3637 "       for (i = 1;i < SAMPLES;i++)\n"
3638 "       {\n"
3639 "               color += texture2D(Texture_First, tc).rgb;\n"
3640 "               tc += BloomBlur_Parameters.xy;\n"
3641 "       }\n"
3642 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
3643 "}\n"
3644 "#endif\n"
3645 "#else // !MODE_BLOOMBLUR\n"
3646 "#ifdef MODE_REFRACTION\n"
3647 "varying mediump vec2 TexCoord;\n"
3648 "varying highp vec4 ModelViewProjectionPosition;\n"
3649 "uniform highp mat4 TexMatrix;\n"
3650 "#ifdef VERTEX_SHADER\n"
3651 "\n"
3652 "void main(void)\n"
3653 "{\n"
3654 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
3655 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
3656 "       ModelViewProjectionPosition = gl_Position;\n"
3657 "}\n"
3658 "#endif\n"
3659 "\n"
3660 "#ifdef FRAGMENT_SHADER\n"
3661 "uniform sampler2D Texture_Normal;\n"
3662 "uniform sampler2D Texture_Refraction;\n"
3663 "uniform sampler2D Texture_Reflection;\n"
3664 "\n"
3665 "uniform mediump vec4 DistortScaleRefractReflect;\n"
3666 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
3667 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
3668 "uniform lowp vec4 RefractColor;\n"
3669 "uniform lowp vec4 ReflectColor;\n"
3670 "uniform mediump float ReflectFactor;\n"
3671 "uniform mediump float ReflectOffset;\n"
3672 "\n"
3673 "void main(void)\n"
3674 "{\n"
3675 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
3676 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
3677 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
3678 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
3679 "       // FIXME temporary hack to detect the case that the reflection\n"
3680 "       // gets blackened at edges due to leaving the area that contains actual\n"
3681 "       // content.\n"
3682 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3683 "       // 'appening.\n"
3684 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
3685 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
3686 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
3687 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
3688 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3689 "       gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
3690 "}\n"
3691 "#endif\n"
3692 "#else // !MODE_REFRACTION\n"
3693 "\n"
3694 "\n"
3695 "\n"
3696 "\n"
3697 "#ifdef MODE_WATER\n"
3698 "varying mediump vec2 TexCoord;\n"
3699 "varying highp vec3 EyeVector;\n"
3700 "varying highp vec4 ModelViewProjectionPosition;\n"
3701 "#ifdef VERTEX_SHADER\n"
3702 "uniform highp vec3 EyePosition;\n"
3703 "uniform highp mat4 TexMatrix;\n"
3704 "\n"
3705 "void main(void)\n"
3706 "{\n"
3707 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
3708 "       vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
3709 "       EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
3710 "       EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
3711 "       EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
3712 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
3713 "       ModelViewProjectionPosition = gl_Position;\n"
3714 "}\n"
3715 "#endif\n"
3716 "\n"
3717 "#ifdef FRAGMENT_SHADER\n"
3718 "uniform sampler2D Texture_Normal;\n"
3719 "uniform sampler2D Texture_Refraction;\n"
3720 "uniform sampler2D Texture_Reflection;\n"
3721 "\n"
3722 "uniform mediump vec4 DistortScaleRefractReflect;\n"
3723 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
3724 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
3725 "uniform lowp vec4 RefractColor;\n"
3726 "uniform lowp vec4 ReflectColor;\n"
3727 "uniform mediump float ReflectFactor;\n"
3728 "uniform mediump float ReflectOffset;\n"
3729 "uniform highp float ClientTime;\n"
3730 "#ifdef USENORMALMAPSCROLLBLEND\n"
3731 "uniform highp vec2 NormalmapScrollBlend;\n"
3732 "#endif\n"
3733 "\n"
3734 "void main(void)\n"
3735 "{\n"
3736 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3737 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3738 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3739 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
3740 "       // slight water animation via 2 layer scrolling (todo: tweak)\n"
3741 "       #ifdef USENORMALMAPSCROLLBLEND\n"
3742 "               vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
3743 "               normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
3744 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
3745 "       #else\n"
3746 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
3747 "       #endif\n"
3748 "       // FIXME temporary hack to detect the case that the reflection\n"
3749 "       // gets blackened at edges due to leaving the area that contains actual\n"
3750 "       // content.\n"
3751 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3752 "       // 'appening.\n"
3753 "       float f  = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
3754 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
3755 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
3756 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
3757 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
3758 "       f  = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
3759 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
3760 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
3761 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
3762 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
3763 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
3764 "       gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
3765 "}\n"
3766 "#endif\n"
3767 "#else // !MODE_WATER\n"
3768 "\n"
3769 "\n"
3770 "\n"
3771 "\n"
3772 "// common definitions between vertex shader and fragment shader:\n"
3773 "\n"
3774 "varying mediump vec2 TexCoord;\n"
3775 "#ifdef USEVERTEXTEXTUREBLEND\n"
3776 "varying mediump vec2 TexCoord2;\n"
3777 "#endif\n"
3778 "#ifdef USELIGHTMAP\n"
3779 "varying mediump vec2 TexCoordLightmap;\n"
3780 "#endif\n"
3781 "\n"
3782 "#ifdef MODE_LIGHTSOURCE\n"
3783 "varying mediump vec3 CubeVector;\n"
3784 "#endif\n"
3785 "\n"
3786 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
3787 "varying mediump vec3 LightVector;\n"
3788 "#endif\n"
3789 "\n"
3790 "#ifdef USEEYEVECTOR\n"
3791 "varying highp vec3 EyeVector;\n"
3792 "#endif\n"
3793 "#ifdef USEFOG\n"
3794 "varying highp vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
3795 "#endif\n"
3796 "\n"
3797 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
3798 "varying lowp vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
3799 "varying lowp vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
3800 "varying lowp vec3 VectorR; // direction of R texcoord (surface normal)\n"
3801 "#endif\n"
3802 "\n"
3803 "#ifdef USEREFLECTION\n"
3804 "varying highp vec4 ModelViewProjectionPosition;\n"
3805 "#endif\n"
3806 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3807 "uniform highp vec3 LightPosition;\n"
3808 "varying highp vec4 ModelViewPosition;\n"
3809 "#endif\n"
3810 "\n"
3811 "#ifdef MODE_LIGHTSOURCE\n"
3812 "uniform highp vec3 LightPosition;\n"
3813 "#endif\n"
3814 "uniform highp vec3 EyePosition;\n"
3815 "#ifdef MODE_LIGHTDIRECTION\n"
3816 "uniform highp vec3 LightDir;\n"
3817 "#endif\n"
3818 "uniform highp vec4 FogPlane;\n"
3819 "\n"
3820 "#ifdef USESHADOWMAPORTHO\n"
3821 "varying mediump vec3 ShadowMapTC;\n"
3822 "#endif\n"
3823 "\n"
3824 "\n"
3825 "\n"
3826 "\n"
3827 "\n"
3828 "// 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"
3829 "\n"
3830 "// fragment shader specific:\n"
3831 "#ifdef FRAGMENT_SHADER\n"
3832 "\n"
3833 "uniform sampler2D Texture_Normal;\n"
3834 "uniform sampler2D Texture_Color;\n"
3835 "uniform sampler2D Texture_Gloss;\n"
3836 "#ifdef USEGLOW\n"
3837 "uniform sampler2D Texture_Glow;\n"
3838 "#endif\n"
3839 "#ifdef USEVERTEXTEXTUREBLEND\n"
3840 "uniform sampler2D Texture_SecondaryNormal;\n"
3841 "uniform sampler2D Texture_SecondaryColor;\n"
3842 "uniform sampler2D Texture_SecondaryGloss;\n"
3843 "#ifdef USEGLOW\n"
3844 "uniform sampler2D Texture_SecondaryGlow;\n"
3845 "#endif\n"
3846 "#endif\n"
3847 "#ifdef USECOLORMAPPING\n"
3848 "uniform sampler2D Texture_Pants;\n"
3849 "uniform sampler2D Texture_Shirt;\n"
3850 "#endif\n"
3851 "#ifdef USEFOG\n"
3852 "#ifdef USEFOGHEIGHTTEXTURE\n"
3853 "uniform sampler2D Texture_FogHeightTexture;\n"
3854 "#endif\n"
3855 "uniform sampler2D Texture_FogMask;\n"
3856 "#endif\n"
3857 "#ifdef USELIGHTMAP\n"
3858 "uniform sampler2D Texture_Lightmap;\n"
3859 "#endif\n"
3860 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
3861 "uniform sampler2D Texture_Deluxemap;\n"
3862 "#endif\n"
3863 "#ifdef USEREFLECTION\n"
3864 "uniform sampler2D Texture_Reflection;\n"
3865 "#endif\n"
3866 "\n"
3867 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3868 "uniform sampler2D Texture_ScreenDepth;\n"
3869 "uniform sampler2D Texture_ScreenNormalMap;\n"
3870 "#endif\n"
3871 "#ifdef USEDEFERREDLIGHTMAP\n"
3872 "uniform sampler2D Texture_ScreenDiffuse;\n"
3873 "uniform sampler2D Texture_ScreenSpecular;\n"
3874 "#endif\n"
3875 "\n"
3876 "uniform lowp vec3 Color_Pants;\n"
3877 "uniform lowp vec3 Color_Shirt;\n"
3878 "uniform lowp vec3 FogColor;\n"
3879 "\n"
3880 "#ifdef USEFOG\n"
3881 "uniform highp float FogRangeRecip;\n"
3882 "uniform highp float FogPlaneViewDist;\n"
3883 "uniform highp float FogHeightFade;\n"
3884 "vec3 FogVertex(vec3 surfacecolor)\n"
3885 "{\n"
3886 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
3887 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
3888 "       float fogfrac;\n"
3889 "#ifdef USEFOGHEIGHTTEXTURE\n"
3890 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
3891 "       fogfrac = fogheightpixel.a;\n"
3892 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
3893 "#else\n"
3894 "# ifdef USEFOGOUTSIDE\n"
3895 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
3896 "# else\n"
3897 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
3898 "# endif\n"
3899 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
3900 "#endif\n"
3901 "}\n"
3902 "#endif\n"
3903 "\n"
3904 "#ifdef USEOFFSETMAPPING\n"
3905 "uniform mediump float OffsetMapping_Scale;\n"
3906 "vec2 OffsetMapping(vec2 TexCoord)\n"
3907 "{\n"
3908 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
3909 "       // 14 sample relief mapping: linear search and then binary search\n"
3910 "       // this basically steps forward a small amount repeatedly until it finds\n"
3911 "       // itself inside solid, then jitters forward and back using decreasing\n"
3912 "       // amounts to find the impact\n"
3913 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
3914 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
3915 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
3916 "       vec3 RT = vec3(TexCoord, 1);\n"
3917 "       OffsetVector *= 0.1;\n"
3918 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
3919 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
3920 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
3921 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
3922 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
3923 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
3924 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
3925 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
3926 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
3927 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
3928 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
3929 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
3930 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
3931 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
3932 "       return RT.xy;\n"
3933 "#else\n"
3934 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
3935 "       // this basically moves forward the full distance, and then backs up based\n"
3936 "       // on height of samples\n"
3937 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
3938 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
3939 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
3940 "       TexCoord += OffsetVector;\n"
3941 "       OffsetVector *= 0.5;\n"
3942 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
3943 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
3944 "       return TexCoord;\n"
3945 "#endif\n"
3946 "}\n"
3947 "#endif // USEOFFSETMAPPING\n"
3948 "\n"
3949 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3950 "uniform sampler2D Texture_Attenuation;\n"
3951 "uniform samplerCube Texture_Cube;\n"
3952 "#endif\n"
3953 "\n"
3954 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3955 "\n"
3956 "#ifdef USESHADOWMAP2D\n"
3957 "# ifdef USESHADOWSAMPLER\n"
3958 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
3959 "# else\n"
3960 "uniform sampler2D Texture_ShadowMap2D;\n"
3961 "# endif\n"
3962 "#endif\n"
3963 "\n"
3964 "#ifdef USESHADOWMAPVSDCT\n"
3965 "uniform samplerCube Texture_CubeProjection;\n"
3966 "#endif\n"
3967 "\n"
3968 "#if defined(USESHADOWMAP2D)\n"
3969 "uniform mediump vec2 ShadowMap_TextureScale;\n"
3970 "uniform mediump vec4 ShadowMap_Parameters;\n"
3971 "#endif\n"
3972 "\n"
3973 "#if defined(USESHADOWMAP2D)\n"
3974 "# ifdef USESHADOWMAPORTHO\n"
3975 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
3976 "# else\n"
3977 "#  ifdef USESHADOWMAPVSDCT\n"
3978 "vec3 GetShadowMapTC2D(vec3 dir)\n"
3979 "{\n"
3980 "       vec3 adir = abs(dir);\n"
3981 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
3982 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
3983 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
3984 "}\n"
3985 "#  else\n"
3986 "vec3 GetShadowMapTC2D(vec3 dir)\n"
3987 "{\n"
3988 "       vec3 adir = abs(dir);\n"
3989 "       float ma = adir.z;\n"
3990 "       vec4 proj = vec4(dir, 2.5);\n"
3991 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
3992 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
3993 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
3994 "       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"
3995 "}\n"
3996 "#  endif\n"
3997 "# endif\n"
3998 "#endif // defined(USESHADOWMAP2D)\n"
3999 "\n"
4000 "# ifdef USESHADOWMAP2D\n"
4001 "float ShadowMapCompare(vec3 dir)\n"
4002 "{\n"
4003 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
4004 "       float f;\n"
4005 "\n"
4006 "#  ifdef USESHADOWSAMPLER\n"
4007 "#    ifdef USESHADOWMAPPCF\n"
4008 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
4009 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
4010 "       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"
4011 "#    else\n"
4012 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
4013 "#    endif\n"
4014 "#  else\n"
4015 "#    ifdef USESHADOWMAPPCF\n"
4016 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
4017 "#      ifdef GL_ARB_texture_gather\n"
4018 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
4019 "#      else\n"
4020 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
4021 "#      endif\n"
4022 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
4023 "#      if USESHADOWMAPPCF > 1\n"
4024 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
4025 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
4026 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
4027 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
4028 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
4029 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
4030 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
4031 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
4032 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
4033 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
4034 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
4035 "       locols.yz += group2.ab;\n"
4036 "       hicols.yz += group8.rg;\n"
4037 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
4038 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
4039 "                               mix(locols, hicols, offset.y);\n"
4040 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
4041 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
4042 "       f = dot(cols, vec4(1.0/25.0));\n"
4043 "#      else\n"
4044 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
4045 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
4046 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
4047 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
4048 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
4049 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
4050 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
4051 "#      endif\n"
4052 "#     else\n"
4053 "#      ifdef GL_EXT_gpu_shader4\n"
4054 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
4055 "#      else\n"
4056 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
4057 "#      endif\n"
4058 "#      if USESHADOWMAPPCF > 1\n"
4059 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
4060 "       center *= ShadowMap_TextureScale;\n"
4061 "       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"
4062 "       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"
4063 "       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"
4064 "       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"
4065 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
4066 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
4067 "#      else\n"
4068 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
4069 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
4070 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
4071 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
4072 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
4073 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
4074 "#      endif\n"
4075 "#     endif\n"
4076 "#    else\n"
4077 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
4078 "#    endif\n"
4079 "#  endif\n"
4080 "#  ifdef USESHADOWMAPORTHO\n"
4081 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
4082 "#  else\n"
4083 "       return f;\n"
4084 "#  endif\n"
4085 "}\n"
4086 "# endif\n"
4087 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
4088 "#endif // FRAGMENT_SHADER\n"
4089 "\n"
4090 "\n"
4091 "\n"
4092 "\n"
4093 "#ifdef MODE_DEFERREDGEOMETRY\n"
4094 "#ifdef VERTEX_SHADER\n"
4095 "uniform highp mat4 TexMatrix;\n"
4096 "#ifdef USEVERTEXTEXTUREBLEND\n"
4097 "uniform highp mat4 BackgroundTexMatrix;\n"
4098 "#endif\n"
4099 "uniform highp mat4 ModelViewMatrix;\n"
4100 "void main(void)\n"
4101 "{\n"
4102 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
4103 "#ifdef USEVERTEXTEXTUREBLEND\n"
4104 "       VertexColor = Attrib_Color;\n"
4105 "       TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
4106 "#endif\n"
4107 "\n"
4108 "       // transform unnormalized eye direction into tangent space\n"
4109 "#ifdef USEOFFSETMAPPING\n"
4110 "       vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
4111 "       EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
4112 "       EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
4113 "       EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
4114 "#endif\n"
4115 "\n"
4116 "       VectorS = (ModelViewMatrix * vec4(Attrib_TexCoord1.xyz, 0)).xyz;\n"
4117 "       VectorT = (ModelViewMatrix * vec4(Attrib_TexCoord2.xyz, 0)).xyz;\n"
4118 "       VectorR = (ModelViewMatrix * vec4(Attrib_TexCoord3.xyz, 0)).xyz;\n"
4119 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
4120 "}\n"
4121 "#endif // VERTEX_SHADER\n"
4122 "\n"
4123 "#ifdef FRAGMENT_SHADER\n"
4124 "void main(void)\n"
4125 "{\n"
4126 "#ifdef USEOFFSETMAPPING\n"
4127 "       // apply offsetmapping\n"
4128 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
4129 "#define TexCoord TexCoordOffset\n"
4130 "#endif\n"
4131 "\n"
4132 "#ifdef USEALPHAKILL\n"
4133 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
4134 "               discard;\n"
4135 "#endif\n"
4136 "\n"
4137 "#ifdef USEVERTEXTEXTUREBLEND\n"
4138 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
4139 "       float terrainblend = clamp(float(VertexColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
4140 "       //float terrainblend = min(float(VertexColor.a) * alpha * 2.0, float(1.0));\n"
4141 "       //float terrainblend = float(VertexColor.a) * alpha > 0.5;\n"
4142 "#endif\n"
4143 "\n"
4144 "#ifdef USEVERTEXTEXTUREBLEND\n"
4145 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
4146 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
4147 "#else\n"
4148 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
4149 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
4150 "#endif\n"
4151 "\n"
4152 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
4153 "}\n"
4154 "#endif // FRAGMENT_SHADER\n"
4155 "#else // !MODE_DEFERREDGEOMETRY\n"
4156 "\n"
4157 "\n"
4158 "\n"
4159 "\n"
4160 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
4161 "#ifdef VERTEX_SHADER\n"
4162 "uniform highp mat4 ModelViewMatrix;\n"
4163 "void main(void)\n"
4164 "{\n"
4165 "       ModelViewPosition = ModelViewMatrix * Attrib_Position;\n"
4166 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
4167 "}\n"
4168 "#endif // VERTEX_SHADER\n"
4169 "\n"
4170 "#ifdef FRAGMENT_SHADER\n"
4171 "uniform highp mat4 ViewToLight;\n"
4172 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
4173 "uniform highp vec2 ScreenToDepth;\n"
4174 "uniform myhalf3 DeferredColor_Ambient;\n"
4175 "uniform myhalf3 DeferredColor_Diffuse;\n"
4176 "#ifdef USESPECULAR\n"
4177 "uniform myhalf3 DeferredColor_Specular;\n"
4178 "uniform myhalf SpecularPower;\n"
4179 "#endif\n"
4180 "uniform myhalf2 PixelToScreenTexCoord;\n"
4181 "void main(void)\n"
4182 "{\n"
4183 "       // calculate viewspace pixel position\n"
4184 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
4185 "       vec3 position;\n"
4186 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
4187 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
4188 "       // decode viewspace pixel normal\n"
4189 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
4190 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
4191 "       // surfacenormal = pixel normal in viewspace\n"
4192 "       // LightVector = pixel to light in viewspace\n"
4193 "       // CubeVector = position in lightspace\n"
4194 "       // eyevector = pixel to view in viewspace\n"
4195 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
4196 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
4197 "#ifdef USEDIFFUSE\n"
4198 "       // calculate diffuse shading\n"
4199 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
4200 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
4201 "#endif\n"
4202 "#ifdef USESPECULAR\n"
4203 "       // calculate directional shading\n"
4204 "       vec3 eyevector = position * -1.0;\n"
4205 "#  ifdef USEEXACTSPECULARMATH\n"
4206 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
4207 "#  else\n"
4208 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
4209 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
4210 "#  endif\n"
4211 "#endif\n"
4212 "\n"
4213 "#if defined(USESHADOWMAP2D)\n"
4214 "       fade *= ShadowMapCompare(CubeVector);\n"
4215 "#endif\n"
4216 "\n"
4217 "#ifdef USEDIFFUSE\n"
4218 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
4219 "#else\n"
4220 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
4221 "#endif\n"
4222 "#ifdef USESPECULAR\n"
4223 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
4224 "#else\n"
4225 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
4226 "#endif\n"
4227 "\n"
4228 "# ifdef USECUBEFILTER\n"
4229 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
4230 "       gl_FragData[0].rgb *= cubecolor;\n"
4231 "       gl_FragData[1].rgb *= cubecolor;\n"
4232 "# endif\n"
4233 "}\n"
4234 "#endif // FRAGMENT_SHADER\n"
4235 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
4236 "\n"
4237 "\n"
4238 "\n"
4239 "\n"
4240 "#ifdef VERTEX_SHADER\n"
4241 "uniform highp mat4 TexMatrix;\n"
4242 "#ifdef USEVERTEXTEXTUREBLEND\n"
4243 "uniform highp mat4 BackgroundTexMatrix;\n"
4244 "#endif\n"
4245 "#ifdef MODE_LIGHTSOURCE\n"
4246 "uniform highp mat4 ModelToLight;\n"
4247 "#endif\n"
4248 "#ifdef USESHADOWMAPORTHO\n"
4249 "uniform highp mat4 ShadowMapMatrix;\n"
4250 "#endif\n"
4251 "void main(void)\n"
4252 "{\n"
4253 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
4254 "       VertexColor = Attrib_Color;\n"
4255 "#endif\n"
4256 "       // copy the surface texcoord\n"
4257 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
4258 "#ifdef USEVERTEXTEXTUREBLEND\n"
4259 "       TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
4260 "#endif\n"
4261 "#ifdef USELIGHTMAP\n"
4262 "       TexCoordLightmap = vec2(Attrib_TexCoord4);\n"
4263 "#endif\n"
4264 "\n"
4265 "#ifdef MODE_LIGHTSOURCE\n"
4266 "       // transform vertex position into light attenuation/cubemap space\n"
4267 "       // (-1 to +1 across the light box)\n"
4268 "       CubeVector = vec3(ModelToLight * Attrib_Position);\n"
4269 "\n"
4270 "# ifdef USEDIFFUSE\n"
4271 "       // transform unnormalized light direction into tangent space\n"
4272 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
4273 "       //  normalize it per pixel)\n"
4274 "       vec3 lightminusvertex = LightPosition - Attrib_Position.xyz;\n"
4275 "       LightVector.x = dot(lightminusvertex, Attrib_TexCoord1.xyz);\n"
4276 "       LightVector.y = dot(lightminusvertex, Attrib_TexCoord2.xyz);\n"
4277 "       LightVector.z = dot(lightminusvertex, Attrib_TexCoord3.xyz);\n"
4278 "# endif\n"
4279 "#endif\n"
4280 "\n"
4281 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
4282 "       LightVector.x = dot(LightDir, Attrib_TexCoord1.xyz);\n"
4283 "       LightVector.y = dot(LightDir, Attrib_TexCoord2.xyz);\n"
4284 "       LightVector.z = dot(LightDir, Attrib_TexCoord3.xyz);\n"
4285 "#endif\n"
4286 "\n"
4287 "       // transform unnormalized eye direction into tangent space\n"
4288 "#ifdef USEEYEVECTOR\n"
4289 "       vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
4290 "       EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
4291 "       EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
4292 "       EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
4293 "#endif\n"
4294 "\n"
4295 "#ifdef USEFOG\n"
4296 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - Attrib_Position.xyz;\n"
4297 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, Attrib_Position);\n"
4298 "#endif\n"
4299 "\n"
4300 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
4301 "       VectorS = Attrib_TexCoord1.xyz;\n"
4302 "       VectorT = Attrib_TexCoord2.xyz;\n"
4303 "       VectorR = Attrib_TexCoord3.xyz;\n"
4304 "#endif\n"
4305 "\n"
4306 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
4307 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
4308 "\n"
4309 "#ifdef USESHADOWMAPORTHO\n"
4310 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
4311 "#endif\n"
4312 "\n"
4313 "#ifdef USEREFLECTION\n"
4314 "       ModelViewProjectionPosition = gl_Position;\n"
4315 "#endif\n"
4316 "}\n"
4317 "#endif // VERTEX_SHADER\n"
4318 "\n"
4319 "\n"
4320 "\n"
4321 "\n"
4322 "#ifdef FRAGMENT_SHADER\n"
4323 "#ifdef USEDEFERREDLIGHTMAP\n"
4324 "uniform myhalf2 PixelToScreenTexCoord;\n"
4325 "uniform myhalf3 DeferredMod_Diffuse;\n"
4326 "uniform myhalf3 DeferredMod_Specular;\n"
4327 "#endif\n"
4328 "uniform myhalf3 Color_Ambient;\n"
4329 "uniform myhalf3 Color_Diffuse;\n"
4330 "uniform myhalf3 Color_Specular;\n"
4331 "uniform myhalf SpecularPower;\n"
4332 "#ifdef USEGLOW\n"
4333 "uniform myhalf3 Color_Glow;\n"
4334 "#endif\n"
4335 "uniform myhalf Alpha;\n"
4336 "#ifdef USEREFLECTION\n"
4337 "uniform mediump vec4 DistortScaleRefractReflect;\n"
4338 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
4339 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
4340 "uniform lowp vec4 ReflectColor;\n"
4341 "#endif\n"
4342 "#ifdef USEREFLECTCUBE\n"
4343 "uniform highp mat4 ModelToReflectCube;\n"
4344 "uniform sampler2D Texture_ReflectMask;\n"
4345 "uniform samplerCube Texture_ReflectCube;\n"
4346 "#endif\n"
4347 "#ifdef MODE_LIGHTDIRECTION\n"
4348 "uniform myhalf3 LightColor;\n"
4349 "#endif\n"
4350 "#ifdef MODE_LIGHTSOURCE\n"
4351 "uniform myhalf3 LightColor;\n"
4352 "#endif\n"
4353 "void main(void)\n"
4354 "{\n"
4355 "#ifdef USEOFFSETMAPPING\n"
4356 "       // apply offsetmapping\n"
4357 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
4358 "#define TexCoord TexCoordOffset\n"
4359 "#endif\n"
4360 "\n"
4361 "       // combine the diffuse textures (base, pants, shirt)\n"
4362 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
4363 "#ifdef USEALPHAKILL\n"
4364 "       if (color.a < 0.5)\n"
4365 "               discard;\n"
4366 "#endif\n"
4367 "       color.a *= Alpha;\n"
4368 "#ifdef USECOLORMAPPING\n"
4369 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
4370 "#endif\n"
4371 "#ifdef USEVERTEXTEXTUREBLEND\n"
4372 "       myhalf terrainblend = clamp(myhalf(VertexColor.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
4373 "       //myhalf terrainblend = min(myhalf(VertexColor.a) * color.a * 2.0, myhalf(1.0));\n"
4374 "       //myhalf terrainblend = myhalf(VertexColor.a) * color.a > 0.5;\n"
4375 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
4376 "       color.a = 1.0;\n"
4377 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
4378 "#endif\n"
4379 "\n"
4380 "       // get the surface normal\n"
4381 "#ifdef USEVERTEXTEXTUREBLEND\n"
4382 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
4383 "#else\n"
4384 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
4385 "#endif\n"
4386 "\n"
4387 "       // get the material colors\n"
4388 "       myhalf3 diffusetex = color.rgb;\n"
4389 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
4390 "# ifdef USEVERTEXTEXTUREBLEND\n"
4391 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
4392 "# else\n"
4393 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
4394 "# endif\n"
4395 "#endif\n"
4396 "\n"
4397 "#ifdef USEREFLECTCUBE\n"
4398 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
4399 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
4400 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
4401 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
4402 "#endif\n"
4403 "\n"
4404 "\n"
4405 "\n"
4406 "\n"
4407 "#ifdef MODE_LIGHTSOURCE\n"
4408 "       // light source\n"
4409 "#ifdef USEDIFFUSE\n"
4410 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
4411 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
4412 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
4413 "#ifdef USESPECULAR\n"
4414 "#ifdef USEEXACTSPECULARMATH\n"
4415 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
4416 "#else\n"
4417 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
4418 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
4419 "#endif\n"
4420 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
4421 "#endif\n"
4422 "#else\n"
4423 "       color.rgb = diffusetex * Color_Ambient;\n"
4424 "#endif\n"
4425 "       color.rgb *= LightColor;\n"
4426 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
4427 "#if defined(USESHADOWMAP2D)\n"
4428 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
4429 "#endif\n"
4430 "# ifdef USECUBEFILTER\n"
4431 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
4432 "# endif\n"
4433 "#endif // MODE_LIGHTSOURCE\n"
4434 "\n"
4435 "\n"
4436 "\n"
4437 "\n"
4438 "#ifdef MODE_LIGHTDIRECTION\n"
4439 "#define SHADING\n"
4440 "#ifdef USEDIFFUSE\n"
4441 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
4442 "#endif\n"
4443 "#define lightcolor LightColor\n"
4444 "#endif // MODE_LIGHTDIRECTION\n"
4445 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
4446 "#define SHADING\n"
4447 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
4448 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
4449 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
4450 "       // convert modelspace light vector to tangentspace\n"
4451 "       myhalf3 lightnormal;\n"
4452 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
4453 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
4454 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
4455 "       lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
4456 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
4457 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
4458 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
4459 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
4460 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
4461 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
4462 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
4463 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
4464 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
4465 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
4466 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
4467 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
4468 "#define SHADING\n"
4469 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
4470 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
4471 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
4472 "#endif\n"
4473 "\n"
4474 "\n"
4475 "\n"
4476 "\n"
4477 "#ifdef MODE_FAKELIGHT\n"
4478 "#define SHADING\n"
4479 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
4480 "myhalf3 lightcolor = myhalf3(1.0);\n"
4481 "#endif // MODE_FAKELIGHT\n"
4482 "\n"
4483 "\n"
4484 "\n"
4485 "\n"
4486 "#ifdef MODE_LIGHTMAP\n"
4487 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
4488 "#endif // MODE_LIGHTMAP\n"
4489 "#ifdef MODE_VERTEXCOLOR\n"
4490 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(VertexColor.rgb) * Color_Diffuse);\n"
4491 "#endif // MODE_VERTEXCOLOR\n"
4492 "#ifdef MODE_FLATCOLOR\n"
4493 "       color.rgb = diffusetex * Color_Ambient;\n"
4494 "#endif // MODE_FLATCOLOR\n"
4495 "\n"
4496 "\n"
4497 "\n"
4498 "\n"
4499 "#ifdef SHADING\n"
4500 "# ifdef USEDIFFUSE\n"
4501 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
4502 "#  ifdef USESPECULAR\n"
4503 "#   ifdef USEEXACTSPECULARMATH\n"
4504 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
4505 "#   else\n"
4506 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
4507 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
4508 "#   endif\n"
4509 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
4510 "#  else\n"
4511 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
4512 "#  endif\n"
4513 "# else\n"
4514 "       color.rgb = diffusetex * Color_Ambient;\n"
4515 "# endif\n"
4516 "#endif\n"
4517 "\n"
4518 "#ifdef USESHADOWMAPORTHO\n"
4519 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
4520 "#endif\n"
4521 "\n"
4522 "#ifdef USEDEFERREDLIGHTMAP\n"
4523 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
4524 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
4525 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
4526 "#endif\n"
4527 "\n"
4528 "#ifdef USEGLOW\n"
4529 "#ifdef USEVERTEXTEXTUREBLEND\n"
4530 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
4531 "#else\n"
4532 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
4533 "#endif\n"
4534 "#endif\n"
4535 "\n"
4536 "#ifdef USEFOG\n"
4537 "       color.rgb = FogVertex(color.rgb);\n"
4538 "#endif\n"
4539 "\n"
4540 "       // 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"
4541 "#ifdef USEREFLECTION\n"
4542 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
4543 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
4544 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
4545 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
4546 "       // FIXME temporary hack to detect the case that the reflection\n"
4547 "       // gets blackened at edges due to leaving the area that contains actual\n"
4548 "       // content.\n"
4549 "       // Remove this 'ack once we have a better way to stop this thing from\n"
4550 "       // 'appening.\n"
4551 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
4552 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
4553 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
4554 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
4555 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
4556 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
4557 "#endif\n"
4558 "\n"
4559 "       gl_FragColor = vec4(color);\n"
4560 "}\n"
4561 "#endif // FRAGMENT_SHADER\n"
4562 "\n"
4563 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
4564 "#endif // !MODE_DEFERREDGEOMETRY\n"
4565 "#endif // !MODE_WATER\n"
4566 "#endif // !MODE_REFRACTION\n"
4567 "#endif // !MODE_BLOOMBLUR\n"
4568 "#endif // !MODE_GENERIC\n"
4569 "#endif // !MODE_POSTPROCESS\n"
4570 "#endif // !MODE_SHOWDEPTH\n"
4571 "#endif // !MODE_DEPTH_OR_SHADOW\n"
4572 ;
4573
4574 char *glslshaderstring = NULL;
4575 char *cgshaderstring = NULL;
4576 char *hlslshaderstring = NULL;
4577
4578 //=======================================================================================================================================================
4579
4580 typedef struct shaderpermutationinfo_s
4581 {
4582         const char *pretext;
4583         const char *name;
4584 }
4585 shaderpermutationinfo_t;
4586
4587 typedef struct shadermodeinfo_s
4588 {
4589         const char *vertexfilename;
4590         const char *geometryfilename;
4591         const char *fragmentfilename;
4592         const char *pretext;
4593         const char *name;
4594 }
4595 shadermodeinfo_t;
4596
4597 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
4598 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
4599 {
4600         {"#define USEDIFFUSE\n", " diffuse"},
4601         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
4602         {"#define USEVIEWTINT\n", " viewtint"},
4603         {"#define USECOLORMAPPING\n", " colormapping"},
4604         {"#define USESATURATION\n", " saturation"},
4605         {"#define USEFOGINSIDE\n", " foginside"},
4606         {"#define USEFOGOUTSIDE\n", " fogoutside"},
4607         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
4608         {"#define USEGAMMARAMPS\n", " gammaramps"},
4609         {"#define USECUBEFILTER\n", " cubefilter"},
4610         {"#define USEGLOW\n", " glow"},
4611         {"#define USEBLOOM\n", " bloom"},
4612         {"#define USESPECULAR\n", " specular"},
4613         {"#define USEPOSTPROCESSING\n", " postprocessing"},
4614         {"#define USEREFLECTION\n", " reflection"},
4615         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
4616         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
4617         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
4618         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
4619         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
4620         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
4621         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
4622         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
4623         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
4624         {"#define USEALPHAKILL\n", " alphakill"},
4625         {"#define USEREFLECTCUBE\n", " reflectcube"},
4626         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
4627 };
4628
4629 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
4630 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
4631 {
4632         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
4633         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
4634         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
4635         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
4636         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
4637         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
4638         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
4639         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
4640         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
4641         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
4642         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
4643         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
4644         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
4645         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
4646         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
4647         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
4648 };
4649
4650 #ifdef SUPPORTCG
4651 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
4652 {
4653         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
4654         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
4655         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
4656         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
4657         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
4658         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
4659         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
4660         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
4661         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
4662         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
4663         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
4664         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
4665         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
4666         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
4667         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
4668         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
4669 };
4670 #endif
4671
4672 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
4673 {
4674         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
4675         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
4676         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
4677         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
4678         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
4679         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
4680         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
4681         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
4682         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
4683         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
4684         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
4685         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
4686         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
4687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
4688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
4689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
4690 };
4691
4692 shadermodeinfo_t gles2shadermodeinfo[SHADERMODE_COUNT] =
4693 {
4694         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_GENERIC\n", " generic"},
4695         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
4696         {"gles2/default.glsl", NULL, NULL                , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
4697         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
4698         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
4699         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
4700         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
4701         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
4702         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
4703         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
4704         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
4705         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
4706         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_WATER\n", " water"},
4707         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
4708         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
4709         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
4710 };
4711
4712 struct r_glsl_permutation_s;
4713 typedef struct r_glsl_permutation_s
4714 {
4715         /// hash lookup data
4716         struct r_glsl_permutation_s *hashnext;
4717         unsigned int mode;
4718         unsigned int permutation;
4719
4720         /// indicates if we have tried compiling this permutation already
4721         qboolean compiled;
4722         /// 0 if compilation failed
4723         int program;
4724         // texture units assigned to each detected uniform
4725         int tex_Texture_First;
4726         int tex_Texture_Second;
4727         int tex_Texture_GammaRamps;
4728         int tex_Texture_Normal;
4729         int tex_Texture_Color;
4730         int tex_Texture_Gloss;
4731         int tex_Texture_Glow;
4732         int tex_Texture_SecondaryNormal;
4733         int tex_Texture_SecondaryColor;
4734         int tex_Texture_SecondaryGloss;
4735         int tex_Texture_SecondaryGlow;
4736         int tex_Texture_Pants;
4737         int tex_Texture_Shirt;
4738         int tex_Texture_FogHeightTexture;
4739         int tex_Texture_FogMask;
4740         int tex_Texture_Lightmap;
4741         int tex_Texture_Deluxemap;
4742         int tex_Texture_Attenuation;
4743         int tex_Texture_Cube;
4744         int tex_Texture_Refraction;
4745         int tex_Texture_Reflection;
4746         int tex_Texture_ShadowMap2D;
4747         int tex_Texture_CubeProjection;
4748         int tex_Texture_ScreenDepth;
4749         int tex_Texture_ScreenNormalMap;
4750         int tex_Texture_ScreenDiffuse;
4751         int tex_Texture_ScreenSpecular;
4752         int tex_Texture_ReflectMask;
4753         int tex_Texture_ReflectCube;
4754         /// locations of detected uniforms in program object, or -1 if not found
4755         int loc_Texture_First;
4756         int loc_Texture_Second;
4757         int loc_Texture_GammaRamps;
4758         int loc_Texture_Normal;
4759         int loc_Texture_Color;
4760         int loc_Texture_Gloss;
4761         int loc_Texture_Glow;
4762         int loc_Texture_SecondaryNormal;
4763         int loc_Texture_SecondaryColor;
4764         int loc_Texture_SecondaryGloss;
4765         int loc_Texture_SecondaryGlow;
4766         int loc_Texture_Pants;
4767         int loc_Texture_Shirt;
4768         int loc_Texture_FogHeightTexture;
4769         int loc_Texture_FogMask;
4770         int loc_Texture_Lightmap;
4771         int loc_Texture_Deluxemap;
4772         int loc_Texture_Attenuation;
4773         int loc_Texture_Cube;
4774         int loc_Texture_Refraction;
4775         int loc_Texture_Reflection;
4776         int loc_Texture_ShadowMap2D;
4777         int loc_Texture_CubeProjection;
4778         int loc_Texture_ScreenDepth;
4779         int loc_Texture_ScreenNormalMap;
4780         int loc_Texture_ScreenDiffuse;
4781         int loc_Texture_ScreenSpecular;
4782         int loc_Texture_ReflectMask;
4783         int loc_Texture_ReflectCube;
4784         int loc_Alpha;
4785         int loc_BloomBlur_Parameters;
4786         int loc_ClientTime;
4787         int loc_Color_Ambient;
4788         int loc_Color_Diffuse;
4789         int loc_Color_Specular;
4790         int loc_Color_Glow;
4791         int loc_Color_Pants;
4792         int loc_Color_Shirt;
4793         int loc_DeferredColor_Ambient;
4794         int loc_DeferredColor_Diffuse;
4795         int loc_DeferredColor_Specular;
4796         int loc_DeferredMod_Diffuse;
4797         int loc_DeferredMod_Specular;
4798         int loc_DistortScaleRefractReflect;
4799         int loc_EyePosition;
4800         int loc_FogColor;
4801         int loc_FogHeightFade;
4802         int loc_FogPlane;
4803         int loc_FogPlaneViewDist;
4804         int loc_FogRangeRecip;
4805         int loc_LightColor;
4806         int loc_LightDir;
4807         int loc_LightPosition;
4808         int loc_OffsetMapping_Scale;
4809         int loc_PixelSize;
4810         int loc_ReflectColor;
4811         int loc_ReflectFactor;
4812         int loc_ReflectOffset;
4813         int loc_RefractColor;
4814         int loc_Saturation;
4815         int loc_ScreenCenterRefractReflect;
4816         int loc_ScreenScaleRefractReflect;
4817         int loc_ScreenToDepth;
4818         int loc_ShadowMap_Parameters;
4819         int loc_ShadowMap_TextureScale;
4820         int loc_SpecularPower;
4821         int loc_UserVec1;
4822         int loc_UserVec2;
4823         int loc_UserVec3;
4824         int loc_UserVec4;
4825         int loc_ViewTintColor;
4826         int loc_ViewToLight;
4827         int loc_ModelToLight;
4828         int loc_TexMatrix;
4829         int loc_BackgroundTexMatrix;
4830         int loc_ModelViewProjectionMatrix;
4831         int loc_ModelViewMatrix;
4832         int loc_PixelToScreenTexCoord;
4833         int loc_ModelToReflectCube;
4834         int loc_ShadowMapMatrix;
4835         int loc_BloomColorSubtract;
4836         int loc_NormalmapScrollBlend;
4837 }
4838 r_glsl_permutation_t;
4839
4840 #define SHADERPERMUTATION_HASHSIZE 256
4841
4842
4843 // non-degradable "lightweight" shader parameters to keep the permutations simpler
4844 // these can NOT degrade! only use for simple stuff
4845 enum
4846 {
4847         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
4848         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
4849         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
4850         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
4851         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
4852         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
4853 };
4854 #define SHADERSTATICPARMS_COUNT 6
4855
4856 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
4857 static int shaderstaticparms_count = 0;
4858
4859 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
4860 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
4861 qboolean R_CompileShader_CheckStaticParms(void)
4862 {
4863         static int r_compileshader_staticparms_save[1];
4864         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
4865         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
4866
4867         // detect all
4868         if (r_glsl_saturation_redcompensate.integer)
4869                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
4870         if (r_shadow_glossexact.integer)
4871                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
4872         if (r_glsl_postprocess.integer)
4873         {
4874                 if (r_glsl_postprocess_uservec1_enable.integer)
4875                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
4876                 if (r_glsl_postprocess_uservec2_enable.integer)
4877                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
4878                 if (r_glsl_postprocess_uservec3_enable.integer)
4879                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
4880                 if (r_glsl_postprocess_uservec4_enable.integer)
4881                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
4882         }
4883         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
4884 }
4885
4886 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
4887         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
4888                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
4889         else \
4890                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
4891 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
4892 {
4893         shaderstaticparms_count = 0;
4894
4895         // emit all
4896         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
4897         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
4898         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
4899         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
4900         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
4901         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
4902 }
4903
4904 /// information about each possible shader permutation
4905 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4906 /// currently selected permutation
4907 r_glsl_permutation_t *r_glsl_permutation;
4908 /// storage for permutations linked in the hash table
4909 memexpandablearray_t r_glsl_permutationarray;
4910
4911 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4912 {
4913         //unsigned int hashdepth = 0;
4914         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4915         r_glsl_permutation_t *p;
4916         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4917         {
4918                 if (p->mode == mode && p->permutation == permutation)
4919                 {
4920                         //if (hashdepth > 10)
4921                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4922                         return p;
4923                 }
4924                 //hashdepth++;
4925         }
4926         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
4927         p->mode = mode;
4928         p->permutation = permutation;
4929         p->hashnext = r_glsl_permutationhash[mode][hashindex];
4930         r_glsl_permutationhash[mode][hashindex] = p;
4931         //if (hashdepth > 10)
4932         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4933         return p;
4934 }
4935
4936 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
4937 {
4938         char *shaderstring;
4939         if (!filename || !filename[0])
4940                 return NULL;
4941         if (!strcmp(filename, "glsl/default.glsl"))
4942         {
4943                 if (!glslshaderstring)
4944                 {
4945                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4946                         if (glslshaderstring)
4947                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4948                         else
4949                                 glslshaderstring = (char *)builtinshaderstring;
4950                 }
4951                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
4952                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
4953                 return shaderstring;
4954         }
4955         if (!strcmp(filename, "gles2/default.glsl"))
4956         {
4957                 if (!glslshaderstring)
4958                 {
4959                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4960                         if (glslshaderstring)
4961                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4962                         else
4963                                 glslshaderstring = (char *)builtingles2shaderstring;
4964                 }
4965                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
4966                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
4967                 return shaderstring;
4968         }
4969         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4970         if (shaderstring)
4971         {
4972                 if (printfromdisknotice)
4973                         Con_DPrintf("from disk %s... ", filename);
4974                 return shaderstring;
4975         }
4976         return shaderstring;
4977 }
4978
4979 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4980 {
4981         int i;
4982         int sampler;
4983         shadermodeinfo_t *modeinfo = vid.renderpath == RENDERPATH_GLES2 ? gles2shadermodeinfo + mode : glslshadermodeinfo + mode;
4984         char *vertexstring, *geometrystring, *fragmentstring;
4985         char permutationname[256];
4986         int vertstrings_count = 0;
4987         int geomstrings_count = 0;
4988         int fragstrings_count = 0;
4989         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4990         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4991         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4992
4993         if (p->compiled)
4994                 return;
4995         p->compiled = true;
4996         p->program = 0;
4997
4998         permutationname[0] = 0;
4999         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
5000         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
5001         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
5002
5003         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
5004
5005         // the first pretext is which type of shader to compile as
5006         // (later these will all be bound together as a program object)
5007         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
5008         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
5009         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
5010
5011         // the second pretext is the mode (for example a light source)
5012         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
5013         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
5014         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
5015         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
5016
5017         // now add all the permutation pretexts
5018         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5019         {
5020                 if (permutation & (1<<i))
5021                 {
5022                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
5023                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
5024                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
5025                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
5026                 }
5027                 else
5028                 {
5029                         // keep line numbers correct
5030                         vertstrings_list[vertstrings_count++] = "\n";
5031                         geomstrings_list[geomstrings_count++] = "\n";
5032                         fragstrings_list[fragstrings_count++] = "\n";
5033                 }
5034         }
5035
5036         // add static parms
5037         R_CompileShader_AddStaticParms(mode, permutation);
5038         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
5039         vertstrings_count += shaderstaticparms_count;
5040         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
5041         geomstrings_count += shaderstaticparms_count;
5042         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
5043         fragstrings_count += shaderstaticparms_count;
5044
5045         // now append the shader text itself
5046         vertstrings_list[vertstrings_count++] = vertexstring;
5047         geomstrings_list[geomstrings_count++] = geometrystring;
5048         fragstrings_list[fragstrings_count++] = fragmentstring;
5049
5050         // if any sources were NULL, clear the respective list
5051         if (!vertexstring)
5052                 vertstrings_count = 0;
5053         if (!geometrystring)
5054                 geomstrings_count = 0;
5055         if (!fragmentstring)
5056                 fragstrings_count = 0;
5057
5058         // compile the shader program
5059         if (vertstrings_count + geomstrings_count + fragstrings_count)
5060                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
5061         if (p->program)
5062         {
5063                 CHECKGLERROR
5064                 qglUseProgram(p->program);CHECKGLERROR
5065                 // look up all the uniform variable names we care about, so we don't
5066                 // have to look them up every time we set them
5067
5068                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
5069                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
5070                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
5071                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
5072                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
5073                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
5074                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
5075                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
5076                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
5077                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
5078                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
5079                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
5080                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
5081                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
5082                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
5083                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
5084                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
5085                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
5086                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
5087                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
5088                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
5089                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
5090                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
5091                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
5092                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
5093                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
5094                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
5095                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
5096                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
5097                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
5098                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
5099                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
5100                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
5101                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
5102                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
5103                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
5104                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
5105                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
5106                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
5107                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
5108                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
5109                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
5110                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
5111                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
5112                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
5113                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
5114                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
5115                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
5116                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
5117                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
5118                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
5119                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
5120                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
5121                 p->loc_OffsetMapping_Scale        = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
5122                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
5123                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
5124                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
5125                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
5126                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
5127                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
5128                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
5129                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
5130                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
5131                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
5132                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
5133                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
5134                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
5135                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
5136                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
5137                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
5138                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
5139                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
5140                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
5141                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
5142                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
5143                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
5144                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
5145                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
5146                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
5147                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
5148                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
5149                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
5150                 // initialize the samplers to refer to the texture units we use
5151                 p->tex_Texture_First = -1;
5152                 p->tex_Texture_Second = -1;
5153                 p->tex_Texture_GammaRamps = -1;
5154                 p->tex_Texture_Normal = -1;
5155                 p->tex_Texture_Color = -1;
5156                 p->tex_Texture_Gloss = -1;
5157                 p->tex_Texture_Glow = -1;
5158                 p->tex_Texture_SecondaryNormal = -1;
5159                 p->tex_Texture_SecondaryColor = -1;
5160                 p->tex_Texture_SecondaryGloss = -1;
5161                 p->tex_Texture_SecondaryGlow = -1;
5162                 p->tex_Texture_Pants = -1;
5163                 p->tex_Texture_Shirt = -1;
5164                 p->tex_Texture_FogHeightTexture = -1;
5165                 p->tex_Texture_FogMask = -1;
5166                 p->tex_Texture_Lightmap = -1;
5167                 p->tex_Texture_Deluxemap = -1;
5168                 p->tex_Texture_Attenuation = -1;
5169                 p->tex_Texture_Cube = -1;
5170                 p->tex_Texture_Refraction = -1;
5171                 p->tex_Texture_Reflection = -1;
5172                 p->tex_Texture_ShadowMap2D = -1;
5173                 p->tex_Texture_CubeProjection = -1;
5174                 p->tex_Texture_ScreenDepth = -1;
5175                 p->tex_Texture_ScreenNormalMap = -1;
5176                 p->tex_Texture_ScreenDiffuse = -1;
5177                 p->tex_Texture_ScreenSpecular = -1;
5178                 p->tex_Texture_ReflectMask = -1;
5179                 p->tex_Texture_ReflectCube = -1;
5180                 sampler = 0;
5181                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
5182                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
5183                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
5184                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
5185                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
5186                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
5187                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
5188                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
5189                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
5190                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
5191                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
5192                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
5193                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
5194                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
5195                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
5196                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
5197                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
5198                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
5199                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
5200                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
5201                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
5202                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
5203                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
5204                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
5205                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
5206                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
5207                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
5208                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
5209                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
5210                 if (vid.renderpath == RENDERPATH_GLES2)
5211                 {
5212                         qglBindAttribLocation(p->program, GLES2ATTRIB_POSITION , "Attrib_Position" );
5213                         qglBindAttribLocation(p->program, GLES2ATTRIB_COLOR    , "Attrib_Color"    );
5214                         qglBindAttribLocation(p->program, GLES2ATTRIB_TEXCOORD0, "Attrib_TexCoord0");
5215                         qglBindAttribLocation(p->program, GLES2ATTRIB_TEXCOORD1, "Attrib_TexCoord1");
5216                         qglBindAttribLocation(p->program, GLES2ATTRIB_TEXCOORD2, "Attrib_TexCoord2");
5217                         qglBindAttribLocation(p->program, GLES2ATTRIB_TEXCOORD3, "Attrib_TexCoord3");
5218                         qglBindAttribLocation(p->program, GLES2ATTRIB_TEXCOORD4, "Attrib_TexCoord4");
5219                         qglBindAttribLocation(p->program, GLES2ATTRIB_TEXCOORD5, "Attrib_TexCoord5");
5220                         qglBindAttribLocation(p->program, GLES2ATTRIB_TEXCOORD6, "Attrib_TexCoord6");
5221                         qglBindAttribLocation(p->program, GLES2ATTRIB_TEXCOORD7, "Attrib_TexCoord7");
5222                 }
5223                 CHECKGLERROR
5224                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
5225         }
5226         else
5227                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
5228
5229         // free the strings
5230         if (vertexstring)
5231                 Mem_Free(vertexstring);
5232         if (geometrystring)
5233                 Mem_Free(geometrystring);
5234         if (fragmentstring)
5235                 Mem_Free(fragmentstring);
5236 }
5237
5238 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
5239 {
5240         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
5241         if (r_glsl_permutation != perm)
5242         {
5243                 r_glsl_permutation = perm;
5244                 if (!r_glsl_permutation->program)
5245                 {
5246                         if (!r_glsl_permutation->compiled)
5247                                 R_GLSL_CompilePermutation(perm, mode, permutation);
5248                         if (!r_glsl_permutation->program)
5249                         {
5250                                 // remove features until we find a valid permutation
5251                                 int i;
5252                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5253                                 {
5254                                         // reduce i more quickly whenever it would not remove any bits
5255                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
5256                                         if (!(permutation & j))
5257                                                 continue;
5258                                         permutation -= j;
5259                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
5260                                         if (!r_glsl_permutation->compiled)
5261                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
5262                                         if (r_glsl_permutation->program)
5263                                                 break;
5264                                 }
5265                                 if (i >= SHADERPERMUTATION_COUNT)
5266                                 {
5267                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
5268                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
5269                                         qglUseProgram(0);CHECKGLERROR
5270                                         return; // no bit left to clear, entire mode is broken
5271                                 }
5272                         }
5273                 }
5274                 CHECKGLERROR
5275                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
5276         }
5277         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5278         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5279         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
5280 }
5281
5282 #ifdef SUPPORTCG
5283 #include <Cg/cgGL.h>
5284 struct r_cg_permutation_s;
5285 typedef struct r_cg_permutation_s
5286 {
5287         /// hash lookup data
5288         struct r_cg_permutation_s *hashnext;
5289         unsigned int mode;
5290         unsigned int permutation;
5291
5292         /// indicates if we have tried compiling this permutation already
5293         qboolean compiled;
5294         /// 0 if compilation failed
5295         CGprogram vprogram;
5296         CGprogram fprogram;
5297         /// locations of detected parameters in programs, or NULL if not found
5298         CGparameter vp_EyePosition;
5299         CGparameter vp_FogPlane;
5300         CGparameter vp_LightDir;
5301         CGparameter vp_LightPosition;
5302         CGparameter vp_ModelToLight;
5303         CGparameter vp_TexMatrix;
5304         CGparameter vp_BackgroundTexMatrix;
5305         CGparameter vp_ModelViewProjectionMatrix;
5306         CGparameter vp_ModelViewMatrix;
5307         CGparameter vp_ShadowMapMatrix;
5308
5309         CGparameter fp_Texture_First;
5310         CGparameter fp_Texture_Second;
5311         CGparameter fp_Texture_GammaRamps;
5312         CGparameter fp_Texture_Normal;
5313         CGparameter fp_Texture_Color;
5314         CGparameter fp_Texture_Gloss;
5315         CGparameter fp_Texture_Glow;
5316         CGparameter fp_Texture_SecondaryNormal;
5317         CGparameter fp_Texture_SecondaryColor;
5318         CGparameter fp_Texture_SecondaryGloss;
5319         CGparameter fp_Texture_SecondaryGlow;
5320         CGparameter fp_Texture_Pants;
5321         CGparameter fp_Texture_Shirt;
5322         CGparameter fp_Texture_FogHeightTexture;
5323         CGparameter fp_Texture_FogMask;
5324         CGparameter fp_Texture_Lightmap;
5325         CGparameter fp_Texture_Deluxemap;
5326         CGparameter fp_Texture_Attenuation;
5327         CGparameter fp_Texture_Cube;
5328         CGparameter fp_Texture_Refraction;
5329         CGparameter fp_Texture_Reflection;
5330         CGparameter fp_Texture_ShadowMap2D;
5331         CGparameter fp_Texture_CubeProjection;
5332         CGparameter fp_Texture_ScreenDepth;
5333         CGparameter fp_Texture_ScreenNormalMap;
5334         CGparameter fp_Texture_ScreenDiffuse;
5335         CGparameter fp_Texture_ScreenSpecular;
5336         CGparameter fp_Texture_ReflectMask;
5337         CGparameter fp_Texture_ReflectCube;
5338         CGparameter fp_Alpha;
5339         CGparameter fp_BloomBlur_Parameters;
5340         CGparameter fp_ClientTime;
5341         CGparameter fp_Color_Ambient;
5342         CGparameter fp_Color_Diffuse;
5343         CGparameter fp_Color_Specular;
5344         CGparameter fp_Color_Glow;
5345         CGparameter fp_Color_Pants;
5346         CGparameter fp_Color_Shirt;
5347         CGparameter fp_DeferredColor_Ambient;
5348         CGparameter fp_DeferredColor_Diffuse;
5349         CGparameter fp_DeferredColor_Specular;
5350         CGparameter fp_DeferredMod_Diffuse;
5351         CGparameter fp_DeferredMod_Specular;
5352         CGparameter fp_DistortScaleRefractReflect;
5353         CGparameter fp_EyePosition;
5354         CGparameter fp_FogColor;
5355         CGparameter fp_FogHeightFade;
5356         CGparameter fp_FogPlane;
5357         CGparameter fp_FogPlaneViewDist;
5358         CGparameter fp_FogRangeRecip;
5359         CGparameter fp_LightColor;
5360         CGparameter fp_LightDir;
5361         CGparameter fp_LightPosition;
5362         CGparameter fp_OffsetMapping_Scale;
5363         CGparameter fp_PixelSize;
5364         CGparameter fp_ReflectColor;
5365         CGparameter fp_ReflectFactor;
5366         CGparameter fp_ReflectOffset;
5367         CGparameter fp_RefractColor;
5368         CGparameter fp_Saturation;
5369         CGparameter fp_ScreenCenterRefractReflect;
5370         CGparameter fp_ScreenScaleRefractReflect;
5371         CGparameter fp_ScreenToDepth;
5372         CGparameter fp_ShadowMap_Parameters;
5373         CGparameter fp_ShadowMap_TextureScale;
5374         CGparameter fp_SpecularPower;
5375         CGparameter fp_UserVec1;
5376         CGparameter fp_UserVec2;
5377         CGparameter fp_UserVec3;
5378         CGparameter fp_UserVec4;
5379         CGparameter fp_ViewTintColor;
5380         CGparameter fp_ViewToLight;
5381         CGparameter fp_PixelToScreenTexCoord;
5382         CGparameter fp_ModelToReflectCube;
5383         CGparameter fp_BloomColorSubtract;
5384         CGparameter fp_NormalmapScrollBlend;
5385 }
5386 r_cg_permutation_t;
5387
5388 /// information about each possible shader permutation
5389 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
5390 /// currently selected permutation
5391 r_cg_permutation_t *r_cg_permutation;
5392 /// storage for permutations linked in the hash table
5393 memexpandablearray_t r_cg_permutationarray;
5394
5395 #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));}}
5396
5397 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
5398 {
5399         //unsigned int hashdepth = 0;
5400         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
5401         r_cg_permutation_t *p;
5402         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
5403         {
5404                 if (p->mode == mode && p->permutation == permutation)
5405                 {
5406                         //if (hashdepth > 10)
5407                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
5408                         return p;
5409                 }
5410                 //hashdepth++;
5411         }
5412         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
5413         p->mode = mode;
5414         p->permutation = permutation;
5415         p->hashnext = r_cg_permutationhash[mode][hashindex];
5416         r_cg_permutationhash[mode][hashindex] = p;
5417         //if (hashdepth > 10)
5418         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
5419         return p;
5420 }
5421
5422 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
5423 {
5424         char *shaderstring;
5425         if (!filename || !filename[0])
5426                 return NULL;
5427         if (!strcmp(filename, "cg/default.cg"))
5428         {
5429                 if (!cgshaderstring)
5430                 {
5431                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
5432                         if (cgshaderstring)
5433                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
5434                         else
5435                                 cgshaderstring = (char *)builtincgshaderstring;
5436                 }
5437                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
5438                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
5439                 return shaderstring;
5440         }
5441         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
5442         if (shaderstring)
5443         {
5444                 if (printfromdisknotice)
5445                         Con_DPrintf("from disk %s... ", filename);
5446                 return shaderstring;
5447         }
5448         return shaderstring;
5449 }
5450
5451 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
5452 {
5453         // TODO: load or create .fp and .vp shader files
5454 }
5455
5456 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
5457 {
5458         int i;
5459         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
5460         int vertstring_length = 0;
5461         int geomstring_length = 0;
5462         int fragstring_length = 0;
5463         char *t;
5464         char *vertexstring, *geometrystring, *fragmentstring;
5465         char *vertstring, *geomstring, *fragstring;
5466         char permutationname[256];
5467         char cachename[256];
5468         CGprofile vertexProfile;
5469         CGprofile fragmentProfile;
5470         int vertstrings_count = 0;
5471         int geomstrings_count = 0;
5472         int fragstrings_count = 0;
5473         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
5474         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
5475         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
5476
5477         if (p->compiled)
5478                 return;
5479         p->compiled = true;
5480         p->vprogram = NULL;
5481         p->fprogram = NULL;
5482
5483         permutationname[0] = 0;
5484         cachename[0] = 0;
5485         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
5486         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
5487         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
5488
5489         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
5490         strlcat(cachename, "cg/", sizeof(cachename));
5491
5492         // the first pretext is which type of shader to compile as
5493         // (later these will all be bound together as a program object)
5494         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
5495         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
5496         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
5497
5498         // the second pretext is the mode (for example a light source)
5499         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
5500         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
5501         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
5502         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
5503         strlcat(cachename, modeinfo->name, sizeof(cachename));
5504
5505         // now add all the permutation pretexts
5506         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5507         {
5508                 if (permutation & (1<<i))
5509                 {
5510                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
5511                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
5512                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
5513                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
5514                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
5515                 }
5516                 else
5517                 {
5518                         // keep line numbers correct
5519                         vertstrings_list[vertstrings_count++] = "\n";
5520                         geomstrings_list[geomstrings_count++] = "\n";
5521                         fragstrings_list[fragstrings_count++] = "\n";
5522                 }
5523         }
5524
5525         // add static parms
5526         R_CompileShader_AddStaticParms(mode, permutation);
5527         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
5528         vertstrings_count += shaderstaticparms_count;
5529         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
5530         geomstrings_count += shaderstaticparms_count;
5531         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
5532         fragstrings_count += shaderstaticparms_count;
5533
5534         // replace spaces in the cachename with _ characters
5535         for (i = 0;cachename[i];i++)
5536                 if (cachename[i] == ' ')
5537                         cachename[i] = '_';
5538
5539         // now append the shader text itself
5540         vertstrings_list[vertstrings_count++] = vertexstring;
5541         geomstrings_list[geomstrings_count++] = geometrystring;
5542         fragstrings_list[fragstrings_count++] = fragmentstring;
5543
5544         // if any sources were NULL, clear the respective list
5545         if (!vertexstring)
5546                 vertstrings_count = 0;
5547         if (!geometrystring)
5548                 geomstrings_count = 0;
5549         if (!fragmentstring)
5550                 fragstrings_count = 0;
5551
5552         vertstring_length = 0;
5553         for (i = 0;i < vertstrings_count;i++)
5554                 vertstring_length += strlen(vertstrings_list[i]);
5555         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
5556         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
5557                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
5558
5559         geomstring_length = 0;
5560         for (i = 0;i < geomstrings_count;i++)
5561                 geomstring_length += strlen(geomstrings_list[i]);
5562         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
5563         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
5564                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
5565
5566         fragstring_length = 0;
5567         for (i = 0;i < fragstrings_count;i++)
5568                 fragstring_length += strlen(fragstrings_list[i]);
5569         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
5570         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
5571                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
5572
5573         CHECKGLERROR
5574         CHECKCGERROR
5575         //vertexProfile = CG_PROFILE_ARBVP1;
5576         //fragmentProfile = CG_PROFILE_ARBFP1;
5577         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
5578         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
5579         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
5580         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
5581         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
5582         CHECKGLERROR
5583
5584         // try to load the cached shader, or generate one
5585         R_CG_CacheShader(p, cachename, vertstring, fragstring);
5586
5587         // if caching failed, do a dynamic compile for now
5588         CHECKCGERROR
5589         if (vertstring[0] && !p->vprogram)
5590                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
5591         CHECKCGERROR
5592         if (fragstring[0] && !p->fprogram)
5593                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
5594         CHECKCGERROR
5595
5596         // look up all the uniform variable names we care about, so we don't
5597         // have to look them up every time we set them
5598         if (p->vprogram)
5599         {
5600                 CHECKCGERROR
5601                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
5602                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
5603                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
5604                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
5605                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
5606                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
5607                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
5608                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
5609                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
5610                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
5611                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
5612                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
5613                 CHECKCGERROR
5614         }
5615         if (p->fprogram)
5616         {
5617                 CHECKCGERROR
5618                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
5619                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
5620                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
5621                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
5622                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
5623                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
5624                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
5625                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
5626                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
5627                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
5628                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
5629                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
5630                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
5631                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
5632                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
5633                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
5634                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
5635                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
5636                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
5637                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
5638                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
5639                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
5640                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
5641                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
5642                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
5643                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
5644                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
5645                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
5646                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
5647                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
5648                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
5649                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
5650                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
5651                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
5652                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
5653                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
5654                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
5655                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
5656                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
5657                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
5658                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
5659                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
5660                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
5661                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
5662                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
5663                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
5664                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
5665                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
5666                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
5667                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
5668                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
5669                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
5670                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
5671                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
5672                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
5673                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
5674                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
5675                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
5676                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
5677                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
5678                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
5679                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
5680                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
5681                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
5682                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
5683                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
5684                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
5685                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
5686                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
5687                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
5688                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
5689                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
5690                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
5691                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
5692                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
5693                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
5694                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
5695                 p->fp_NormalmapScrollBlend       = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
5696                 CHECKCGERROR
5697         }
5698
5699         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
5700                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
5701         else
5702                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
5703
5704         // free the strings
5705         if (vertstring)
5706                 Mem_Free(vertstring);
5707         if (geomstring)
5708                 Mem_Free(geomstring);
5709         if (fragstring)
5710                 Mem_Free(fragstring);
5711         if (vertexstring)
5712                 Mem_Free(vertexstring);
5713         if (geometrystring)
5714                 Mem_Free(geometrystring);
5715         if (fragmentstring)
5716                 Mem_Free(fragmentstring);
5717 }
5718
5719 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
5720 {
5721         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
5722         CHECKGLERROR
5723         CHECKCGERROR
5724         if (r_cg_permutation != perm)
5725         {
5726                 r_cg_permutation = perm;
5727                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
5728                 {
5729                         if (!r_cg_permutation->compiled)
5730                                 R_CG_CompilePermutation(perm, mode, permutation);
5731                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
5732                         {
5733                                 // remove features until we find a valid permutation
5734                                 int i;
5735                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5736                                 {
5737                                         // reduce i more quickly whenever it would not remove any bits
5738                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
5739                                         if (!(permutation & j))
5740                                                 continue;
5741                                         permutation -= j;
5742                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
5743                                         if (!r_cg_permutation->compiled)
5744                                                 R_CG_CompilePermutation(perm, mode, permutation);
5745                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
5746                                                 break;
5747                                 }
5748                                 if (i >= SHADERPERMUTATION_COUNT)
5749                                 {
5750                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
5751                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
5752                                         return; // no bit left to clear, entire mode is broken
5753                                 }
5754                         }
5755                 }
5756                 CHECKGLERROR
5757                 CHECKCGERROR
5758                 if (r_cg_permutation->vprogram)
5759                 {
5760                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
5761                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
5762                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5763                 }
5764                 else
5765                 {
5766                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5767                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5768                 }
5769                 if (r_cg_permutation->fprogram)
5770                 {
5771                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
5772                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
5773                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5774                 }
5775                 else
5776                 {
5777                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5778                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5779                 }
5780         }
5781         CHECKCGERROR
5782         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
5783         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
5784         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
5785 }
5786
5787 void CG_BindTexture(CGparameter param, rtexture_t *tex)
5788 {
5789         cgGLSetTextureParameter(param, R_GetTexture(tex));
5790         cgGLEnableTextureParameter(param);
5791 }
5792 #endif
5793
5794 #ifdef SUPPORTD3D
5795
5796 #ifdef SUPPORTD3D
5797 #include <d3d9.h>
5798 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
5799 extern D3DCAPS9 vid_d3d9caps;
5800 #endif
5801
5802 struct r_hlsl_permutation_s;
5803 typedef struct r_hlsl_permutation_s
5804 {
5805         /// hash lookup data
5806         struct r_hlsl_permutation_s *hashnext;
5807         unsigned int mode;
5808         unsigned int permutation;
5809
5810         /// indicates if we have tried compiling this permutation already
5811         qboolean compiled;
5812         /// NULL if compilation failed
5813         IDirect3DVertexShader9 *vertexshader;
5814         IDirect3DPixelShader9 *pixelshader;
5815 }
5816 r_hlsl_permutation_t;
5817
5818 typedef enum D3DVSREGISTER_e
5819 {
5820         D3DVSREGISTER_TexMatrix = 0, // float4x4
5821         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
5822         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
5823         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
5824         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
5825         D3DVSREGISTER_ModelToLight = 20, // float4x4
5826         D3DVSREGISTER_EyePosition = 24,
5827         D3DVSREGISTER_FogPlane = 25,
5828         D3DVSREGISTER_LightDir = 26,
5829         D3DVSREGISTER_LightPosition = 27,
5830 }
5831 D3DVSREGISTER_t;
5832
5833 typedef enum D3DPSREGISTER_e
5834 {
5835         D3DPSREGISTER_Alpha = 0,
5836         D3DPSREGISTER_BloomBlur_Parameters = 1,
5837         D3DPSREGISTER_ClientTime = 2,
5838         D3DPSREGISTER_Color_Ambient = 3,
5839         D3DPSREGISTER_Color_Diffuse = 4,
5840         D3DPSREGISTER_Color_Specular = 5,
5841         D3DPSREGISTER_Color_Glow = 6,
5842         D3DPSREGISTER_Color_Pants = 7,
5843         D3DPSREGISTER_Color_Shirt = 8,
5844         D3DPSREGISTER_DeferredColor_Ambient = 9,
5845         D3DPSREGISTER_DeferredColor_Diffuse = 10,
5846         D3DPSREGISTER_DeferredColor_Specular = 11,
5847         D3DPSREGISTER_DeferredMod_Diffuse = 12,
5848         D3DPSREGISTER_DeferredMod_Specular = 13,
5849         D3DPSREGISTER_DistortScaleRefractReflect = 14,
5850         D3DPSREGISTER_EyePosition = 15, // unused
5851         D3DPSREGISTER_FogColor = 16,
5852         D3DPSREGISTER_FogHeightFade = 17,
5853         D3DPSREGISTER_FogPlane = 18,
5854         D3DPSREGISTER_FogPlaneViewDist = 19,
5855         D3DPSREGISTER_FogRangeRecip = 20,
5856         D3DPSREGISTER_LightColor = 21,
5857         D3DPSREGISTER_LightDir = 22, // unused
5858         D3DPSREGISTER_LightPosition = 23,
5859         D3DPSREGISTER_OffsetMapping_Scale = 24,
5860         D3DPSREGISTER_PixelSize = 25,
5861         D3DPSREGISTER_ReflectColor = 26,
5862         D3DPSREGISTER_ReflectFactor = 27,
5863         D3DPSREGISTER_ReflectOffset = 28,
5864         D3DPSREGISTER_RefractColor = 29,
5865         D3DPSREGISTER_Saturation = 30,
5866         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
5867         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
5868         D3DPSREGISTER_ScreenToDepth = 33,
5869         D3DPSREGISTER_ShadowMap_Parameters = 34,
5870         D3DPSREGISTER_ShadowMap_TextureScale = 35,
5871         D3DPSREGISTER_SpecularPower = 36,
5872         D3DPSREGISTER_UserVec1 = 37,
5873         D3DPSREGISTER_UserVec2 = 38,
5874         D3DPSREGISTER_UserVec3 = 39,
5875         D3DPSREGISTER_UserVec4 = 40,
5876         D3DPSREGISTER_ViewTintColor = 41,
5877         D3DPSREGISTER_PixelToScreenTexCoord = 42,
5878         D3DPSREGISTER_BloomColorSubtract = 43,
5879         D3DPSREGISTER_ViewToLight = 44, // float4x4
5880         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
5881         D3DPSREGISTER_NormalmapScrollBlend = 52,
5882         // next at 53
5883 }
5884 D3DPSREGISTER_t;
5885
5886 /// information about each possible shader permutation
5887 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
5888 /// currently selected permutation
5889 r_hlsl_permutation_t *r_hlsl_permutation;
5890 /// storage for permutations linked in the hash table
5891 memexpandablearray_t r_hlsl_permutationarray;
5892
5893 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
5894 {
5895         //unsigned int hashdepth = 0;
5896         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
5897         r_hlsl_permutation_t *p;
5898         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
5899         {
5900                 if (p->mode == mode && p->permutation == permutation)
5901                 {
5902                         //if (hashdepth > 10)
5903                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
5904                         return p;
5905                 }
5906                 //hashdepth++;
5907         }
5908         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
5909         p->mode = mode;
5910         p->permutation = permutation;
5911         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
5912         r_hlsl_permutationhash[mode][hashindex] = p;
5913         //if (hashdepth > 10)
5914         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
5915         return p;
5916 }
5917
5918 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
5919 {
5920         char *shaderstring;
5921         if (!filename || !filename[0])
5922                 return NULL;
5923         if (!strcmp(filename, "hlsl/default.hlsl"))
5924         {
5925                 if (!hlslshaderstring)
5926                 {
5927                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
5928                         if (hlslshaderstring)
5929                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
5930                         else
5931                                 hlslshaderstring = (char *)builtincgshaderstring;
5932                 }
5933                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
5934                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
5935                 return shaderstring;
5936         }
5937         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
5938         if (shaderstring)
5939         {
5940                 if (printfromdisknotice)
5941                         Con_DPrintf("from disk %s... ", filename);
5942                 return shaderstring;
5943         }
5944         return shaderstring;
5945 }
5946
5947 #include <d3dx9.h>
5948 //#include <d3dx9shader.h>
5949 //#include <d3dx9mesh.h>
5950
5951 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
5952 {
5953         DWORD *vsbin = NULL;
5954         DWORD *psbin = NULL;
5955         fs_offset_t vsbinsize;
5956         fs_offset_t psbinsize;
5957 //      IDirect3DVertexShader9 *vs = NULL;
5958 //      IDirect3DPixelShader9 *ps = NULL;
5959         ID3DXBuffer *vslog = NULL;
5960         ID3DXBuffer *vsbuffer = NULL;
5961         ID3DXConstantTable *vsconstanttable = NULL;
5962         ID3DXBuffer *pslog = NULL;
5963         ID3DXBuffer *psbuffer = NULL;
5964         ID3DXConstantTable *psconstanttable = NULL;
5965         int vsresult = 0;
5966         int psresult = 0;
5967         char temp[MAX_INPUTLINE];
5968         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
5969         qboolean debugshader = gl_paranoid.integer != 0;
5970         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
5971         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
5972         if (!debugshader)
5973         {
5974                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
5975                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
5976         }
5977         if ((!vsbin && vertstring) || (!psbin && fragstring))
5978         {
5979                 const char* dllnames_d3dx9 [] =
5980                 {
5981                         "d3dx9_43.dll",
5982                         "d3dx9_42.dll",
5983                         "d3dx9_41.dll",
5984                         "d3dx9_40.dll",
5985                         "d3dx9_39.dll",
5986                         "d3dx9_38.dll",
5987                         "d3dx9_37.dll",
5988                         "d3dx9_36.dll",
5989                         "d3dx9_35.dll",
5990                         "d3dx9_34.dll",
5991                         "d3dx9_33.dll",
5992                         "d3dx9_32.dll",
5993                         "d3dx9_31.dll",
5994                         "d3dx9_30.dll",
5995                         "d3dx9_29.dll",
5996                         "d3dx9_28.dll",
5997                         "d3dx9_27.dll",
5998                         "d3dx9_26.dll",
5999                         "d3dx9_25.dll",
6000                         "d3dx9_24.dll",
6001                         NULL
6002                 };
6003                 dllhandle_t d3dx9_dll = NULL;
6004                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
6005                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
6006                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
6007                 dllfunction_t d3dx9_dllfuncs[] =
6008                 {
6009                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
6010                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
6011                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
6012                         {NULL, NULL}
6013                 };
6014                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
6015                 {
6016                         DWORD shaderflags = 0;
6017                         if (debugshader)
6018                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
6019                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
6020                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
6021                         if (vertstring && vertstring[0])
6022                         {
6023                                 if (debugshader)
6024                                 {
6025 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
6026 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
6027                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
6028                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
6029                                 }
6030                                 else
6031                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
6032                                 if (vsbuffer)
6033                                 {
6034                                         vsbinsize = vsbuffer->GetBufferSize();
6035                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
6036                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
6037                                         vsbuffer->Release();
6038                                 }
6039                                 if (vslog)
6040                                 {
6041                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
6042                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
6043                                         vslog->Release();
6044                                 }
6045                         }
6046                         if (fragstring && fragstring[0])
6047                         {
6048                                 if (debugshader)
6049                                 {
6050 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
6051 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
6052                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
6053                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
6054                                 }
6055                                 else
6056                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
6057                                 if (psbuffer)
6058                                 {
6059                                         psbinsize = psbuffer->GetBufferSize();
6060                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
6061                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
6062                                         psbuffer->Release();
6063                                 }
6064                                 if (pslog)
6065                                 {
6066                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
6067                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
6068                                         pslog->Release();
6069                                 }
6070                         }
6071                         Sys_UnloadLibrary(&d3dx9_dll);
6072                 }
6073                 else
6074                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
6075         }
6076         if (vsbin && psbin)
6077         {
6078                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
6079                 if (FAILED(vsresult))
6080                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
6081                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
6082                 if (FAILED(psresult))
6083                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
6084         }
6085         // free the shader data
6086         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
6087         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
6088 }
6089
6090 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
6091 {
6092         int i;
6093         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
6094         int vertstring_length = 0;
6095         int geomstring_length = 0;
6096         int fragstring_length = 0;
6097         char *t;
6098         char *vertexstring, *geometrystring, *fragmentstring;
6099         char *vertstring, *geomstring, *fragstring;
6100         char permutationname[256];
6101         char cachename[256];
6102         int vertstrings_count = 0;
6103         int geomstrings_count = 0;
6104         int fragstrings_count = 0;
6105         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
6106         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
6107         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
6108
6109         if (p->compiled)
6110                 return;
6111         p->compiled = true;
6112         p->vertexshader = NULL;
6113         p->pixelshader = NULL;
6114
6115         permutationname[0] = 0;
6116         cachename[0] = 0;
6117         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
6118         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
6119         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
6120
6121         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
6122         strlcat(cachename, "hlsl/", sizeof(cachename));
6123
6124         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
6125         vertstrings_count = 0;
6126         geomstrings_count = 0;
6127         fragstrings_count = 0;
6128         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
6129         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
6130         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
6131
6132         // the first pretext is which type of shader to compile as
6133         // (later these will all be bound together as a program object)
6134         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
6135         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
6136         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
6137
6138         // the second pretext is the mode (for example a light source)
6139         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
6140         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
6141         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
6142         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
6143         strlcat(cachename, modeinfo->name, sizeof(cachename));
6144
6145         // now add all the permutation pretexts
6146         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
6147         {
6148                 if (permutation & (1<<i))
6149                 {
6150                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
6151                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
6152                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
6153                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
6154                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
6155                 }
6156                 else
6157                 {
6158                         // keep line numbers correct
6159                         vertstrings_list[vertstrings_count++] = "\n";
6160                         geomstrings_list[geomstrings_count++] = "\n";
6161                         fragstrings_list[fragstrings_count++] = "\n";
6162                 }
6163         }
6164
6165         // add static parms
6166         R_CompileShader_AddStaticParms(mode, permutation);
6167         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
6168         vertstrings_count += shaderstaticparms_count;
6169         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
6170         geomstrings_count += shaderstaticparms_count;
6171         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
6172         fragstrings_count += shaderstaticparms_count;
6173
6174         // replace spaces in the cachename with _ characters
6175         for (i = 0;cachename[i];i++)
6176                 if (cachename[i] == ' ')
6177                         cachename[i] = '_';
6178
6179         // now append the shader text itself
6180         vertstrings_list[vertstrings_count++] = vertexstring;
6181         geomstrings_list[geomstrings_count++] = geometrystring;
6182         fragstrings_list[fragstrings_count++] = fragmentstring;
6183
6184         // if any sources were NULL, clear the respective list
6185         if (!vertexstring)
6186                 vertstrings_count = 0;
6187         if (!geometrystring)
6188                 geomstrings_count = 0;
6189         if (!fragmentstring)
6190                 fragstrings_count = 0;
6191
6192         vertstring_length = 0;
6193         for (i = 0;i < vertstrings_count;i++)
6194                 vertstring_length += strlen(vertstrings_list[i]);
6195         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
6196         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
6197                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
6198
6199         geomstring_length = 0;
6200         for (i = 0;i < geomstrings_count;i++)
6201                 geomstring_length += strlen(geomstrings_list[i]);
6202         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
6203         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
6204                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
6205
6206         fragstring_length = 0;
6207         for (i = 0;i < fragstrings_count;i++)
6208                 fragstring_length += strlen(fragstrings_list[i]);
6209         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
6210         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
6211                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
6212
6213         // try to load the cached shader, or generate one
6214         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
6215
6216         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
6217                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
6218         else
6219                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
6220
6221         // free the strings
6222         if (vertstring)
6223                 Mem_Free(vertstring);
6224         if (geomstring)
6225                 Mem_Free(geomstring);
6226         if (fragstring)
6227                 Mem_Free(fragstring);
6228         if (vertexstring)
6229                 Mem_Free(vertexstring);
6230         if (geometrystring)
6231                 Mem_Free(geometrystring);
6232         if (fragmentstring)
6233                 Mem_Free(fragmentstring);
6234 }
6235
6236 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
6237 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
6238 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
6239 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
6240 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
6241 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
6242
6243 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
6244 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
6245 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
6246 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
6247 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
6248 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
6249
6250 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
6251 {
6252         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
6253         if (r_hlsl_permutation != perm)
6254         {
6255                 r_hlsl_permutation = perm;
6256                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
6257                 {
6258                         if (!r_hlsl_permutation->compiled)
6259                                 R_HLSL_CompilePermutation(perm, mode, permutation);
6260                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
6261                         {
6262                                 // remove features until we find a valid permutation
6263                                 int i;
6264                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
6265                                 {
6266                                         // reduce i more quickly whenever it would not remove any bits
6267                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
6268                                         if (!(permutation & j))
6269                                                 continue;
6270                                         permutation -= j;
6271                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
6272                                         if (!r_hlsl_permutation->compiled)
6273                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
6274                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
6275                                                 break;
6276                                 }
6277                                 if (i >= SHADERPERMUTATION_COUNT)
6278                                 {
6279                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
6280                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
6281                                         return; // no bit left to clear, entire mode is broken
6282                                 }
6283                         }
6284                 }
6285                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
6286                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
6287         }
6288         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
6289         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
6290         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
6291 }
6292 #endif
6293
6294 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
6295 {
6296         DPSOFTRAST_SetShader(mode, permutation);
6297         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
6298         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
6299         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
6300 }
6301
6302 void R_GLSL_Restart_f(void)
6303 {
6304         unsigned int i, limit;
6305         if (glslshaderstring && glslshaderstring != builtinshaderstring && glslshaderstring != builtingles2shaderstring)
6306                 Mem_Free(glslshaderstring);
6307         glslshaderstring = NULL;
6308         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
6309                 Mem_Free(cgshaderstring);
6310         cgshaderstring = NULL;
6311         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
6312                 Mem_Free(hlslshaderstring);
6313         hlslshaderstring = NULL;
6314         switch(vid.renderpath)
6315         {
6316         case RENDERPATH_D3D9:
6317 #ifdef SUPPORTD3D
6318                 {
6319                         r_hlsl_permutation_t *p;
6320                         r_hlsl_permutation = NULL;
6321 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
6322 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
6323 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
6324 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
6325                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
6326                         for (i = 0;i < limit;i++)
6327                         {
6328                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
6329                                 {
6330                                         if (p->vertexshader)
6331                                                 IDirect3DVertexShader9_Release(p->vertexshader);
6332                                         if (p->pixelshader)
6333                                                 IDirect3DPixelShader9_Release(p->pixelshader);
6334                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
6335                                 }
6336                         }
6337                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6338                 }
6339 #endif
6340                 break;
6341         case RENDERPATH_D3D10:
6342                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6343                 break;
6344         case RENDERPATH_D3D11:
6345                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6346                 break;
6347         case RENDERPATH_GL20:
6348         case RENDERPATH_GLES2:
6349                 {
6350                         r_glsl_permutation_t *p;
6351                         r_glsl_permutation = NULL;
6352                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
6353                         for (i = 0;i < limit;i++)
6354                         {
6355                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
6356                                 {
6357                                         GL_Backend_FreeProgram(p->program);
6358                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
6359                                 }
6360                         }
6361                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6362                 }
6363                 break;
6364         case RENDERPATH_CGGL:
6365 #ifdef SUPPORTCG
6366                 {
6367                         r_cg_permutation_t *p;
6368                         r_cg_permutation = NULL;
6369                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
6370                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
6371                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
6372                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
6373                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
6374                         for (i = 0;i < limit;i++)
6375                         {
6376                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
6377                                 {
6378                                         if (p->vprogram)
6379                                                 cgDestroyProgram(p->vprogram);
6380                                         if (p->fprogram)
6381                                                 cgDestroyProgram(p->fprogram);
6382                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
6383                                 }
6384                         }
6385                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6386                 }
6387 #endif
6388                 break;
6389         case RENDERPATH_GL13:
6390         case RENDERPATH_GL11:
6391                 break;
6392         case RENDERPATH_SOFT:
6393                 break;
6394         }
6395 }
6396
6397 void R_GLSL_DumpShader_f(void)
6398 {
6399         int i;
6400         qfile_t *file;
6401
6402         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
6403         if (file)
6404         {
6405                 FS_Print(file, "/* The engine may define the following macros:\n");
6406                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
6407                 for (i = 0;i < SHADERMODE_COUNT;i++)
6408                         FS_Print(file, glslshadermodeinfo[i].pretext);
6409                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
6410                         FS_Print(file, shaderpermutationinfo[i].pretext);
6411                 FS_Print(file, "*/\n");
6412                 FS_Print(file, builtinshaderstring);
6413                 FS_Close(file);
6414                 Con_Printf("glsl/default.glsl written\n");
6415         }
6416         else
6417                 Con_Printf("failed to write to glsl/default.glsl\n");
6418
6419         file = FS_OpenRealFile("gles2/default.glsl", "w", false);
6420         if (file)
6421         {
6422                 FS_Print(file, "/* The engine may define the following macros:\n");
6423                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
6424                 for (i = 0;i < SHADERMODE_COUNT;i++)
6425                         FS_Print(file, glslshadermodeinfo[i].pretext);
6426                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
6427                         FS_Print(file, shaderpermutationinfo[i].pretext);
6428                 FS_Print(file, "*/\n");
6429                 FS_Print(file, builtingles2shaderstring);
6430                 FS_Close(file);
6431                 Con_Printf("gles2/default.glsl written\n");
6432         }
6433         else
6434                 Con_Printf("failed to write to glsl/default.glsl\n");
6435
6436 #ifdef SUPPORTCG
6437         file = FS_OpenRealFile("cg/default.cg", "w", false);
6438         if (file)
6439         {
6440                 FS_Print(file, "/* The engine may define the following macros:\n");
6441                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
6442                 for (i = 0;i < SHADERMODE_COUNT;i++)
6443                         FS_Print(file, cgshadermodeinfo[i].pretext);
6444                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
6445                         FS_Print(file, shaderpermutationinfo[i].pretext);
6446                 FS_Print(file, "*/\n");
6447                 FS_Print(file, builtincgshaderstring);
6448                 FS_Close(file);
6449                 Con_Printf("cg/default.cg written\n");
6450         }
6451         else
6452                 Con_Printf("failed to write to cg/default.cg\n");
6453 #endif
6454
6455         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
6456         if (file)
6457         {
6458                 FS_Print(file, "/* The engine may define the following macros:\n");
6459                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
6460                 for (i = 0;i < SHADERMODE_COUNT;i++)
6461                         FS_Print(file, hlslshadermodeinfo[i].pretext);
6462                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
6463                         FS_Print(file, shaderpermutationinfo[i].pretext);
6464                 FS_Print(file, "*/\n");
6465                 FS_Print(file, builtincgshaderstring);
6466                 FS_Close(file);
6467                 Con_Printf("hlsl/default.hlsl written\n");
6468         }
6469         else
6470                 Con_Printf("failed to write to hlsl/default.hlsl\n");
6471 }
6472
6473 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
6474 {
6475         if (!second)
6476                 texturemode = GL_MODULATE;
6477         switch (vid.renderpath)
6478         {
6479         case RENDERPATH_D3D9:
6480 #ifdef SUPPORTD3D
6481                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
6482                 R_Mesh_TexBind(GL20TU_FIRST , first );
6483                 R_Mesh_TexBind(GL20TU_SECOND, second);
6484 #endif
6485                 break;
6486         case RENDERPATH_D3D10:
6487                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6488                 break;
6489         case RENDERPATH_D3D11:
6490                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6491                 break;
6492         case RENDERPATH_GL20:
6493         case RENDERPATH_GLES2:
6494                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
6495                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
6496                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
6497                 break;
6498         case RENDERPATH_CGGL:
6499 #ifdef SUPPORTCG
6500                 CHECKCGERROR
6501                 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
6502                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
6503                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
6504 #endif
6505                 break;
6506         case RENDERPATH_GL13:
6507                 R_Mesh_TexBind(0, first );
6508                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
6509                 R_Mesh_TexBind(1, second);
6510                 if (second)
6511                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
6512                 break;
6513         case RENDERPATH_GL11:
6514                 R_Mesh_TexBind(0, first );
6515                 break;
6516         case RENDERPATH_SOFT:
6517                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
6518                 R_Mesh_TexBind(GL20TU_FIRST , first );
6519                 R_Mesh_TexBind(GL20TU_SECOND, second);
6520                 break;
6521         }
6522 }
6523
6524 void R_SetupShader_DepthOrShadow(void)
6525 {
6526         switch (vid.renderpath)
6527         {
6528         case RENDERPATH_D3D9:
6529 #ifdef SUPPORTD3D
6530                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
6531 #endif
6532                 break;
6533         case RENDERPATH_D3D10:
6534                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6535                 break;
6536         case RENDERPATH_D3D11:
6537                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6538                 break;
6539         case RENDERPATH_GL20:
6540         case RENDERPATH_GLES2:
6541                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
6542                 break;
6543         case RENDERPATH_CGGL:
6544 #ifdef SUPPORTCG
6545                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
6546 #endif
6547                 break;
6548         case RENDERPATH_GL13:
6549                 R_Mesh_TexBind(0, 0);
6550                 R_Mesh_TexBind(1, 0);
6551                 break;
6552         case RENDERPATH_GL11:
6553                 R_Mesh_TexBind(0, 0);
6554                 break;
6555         case RENDERPATH_SOFT:
6556                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
6557                 break;
6558         }
6559 }
6560
6561 void R_SetupShader_ShowDepth(void)
6562 {
6563         switch (vid.renderpath)
6564         {
6565         case RENDERPATH_D3D9:
6566 #ifdef SUPPORTHLSL
6567                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
6568 #endif
6569                 break;
6570         case RENDERPATH_D3D10:
6571                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6572                 break;
6573         case RENDERPATH_D3D11:
6574                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6575                 break;
6576         case RENDERPATH_GL20:
6577         case RENDERPATH_GLES2:
6578                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
6579                 break;
6580         case RENDERPATH_CGGL:
6581 #ifdef SUPPORTCG
6582                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
6583 #endif
6584                 break;
6585         case RENDERPATH_GL13:
6586                 break;
6587         case RENDERPATH_GL11:
6588                 break;
6589         case RENDERPATH_SOFT:
6590                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
6591                 break;
6592         }
6593 }
6594
6595 extern qboolean r_shadow_usingdeferredprepass;
6596 extern cvar_t r_shadow_deferred_8bitrange;
6597 extern rtexture_t *r_shadow_attenuationgradienttexture;
6598 extern rtexture_t *r_shadow_attenuation2dtexture;
6599 extern rtexture_t *r_shadow_attenuation3dtexture;
6600 extern qboolean r_shadow_usingshadowmap2d;
6601 extern qboolean r_shadow_usingshadowmaportho;
6602 extern float r_shadow_shadowmap_texturescale[2];
6603 extern float r_shadow_shadowmap_parameters[4];
6604 extern qboolean r_shadow_shadowmapvsdct;
6605 extern qboolean r_shadow_shadowmapsampler;
6606 extern int r_shadow_shadowmappcf;
6607 extern rtexture_t *r_shadow_shadowmap2dtexture;
6608 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
6609 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
6610 extern matrix4x4_t r_shadow_shadowmapmatrix;
6611 extern int r_shadow_shadowmaplod; // changes for each light based on distance
6612 extern int r_shadow_prepass_width;
6613 extern int r_shadow_prepass_height;
6614 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
6615 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
6616 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
6617 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
6618 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
6619 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
6620 {
6621         // a blendfunc allows colormod if:
6622         // a) it can never keep the destination pixel invariant, or
6623         // b) it can keep the destination pixel invariant, and still can do so if colormodded
6624         // this is to prevent unintended side effects from colormod
6625
6626         // in formulas:
6627         // IF there is a (s, sa) for which for all (d, da),
6628         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
6629         // THEN, for this (s, sa) and all (colormod, d, da):
6630         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
6631         // OBVIOUSLY, this means that
6632         //   s*colormod * src(s*colormod, d, sa, da) = 0
6633         //   dst(s*colormod, d, sa, da)              = 1
6634
6635         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
6636
6637         // main condition to leave dst color invariant:
6638         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
6639         //   src == GL_ZERO:
6640         //     s * 0 + d * dst(s, d, sa, da) == d
6641         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
6642         //       => colormod is a problem for GL_SRC_COLOR only
6643         //   src == GL_ONE:
6644         //     s + d * dst(s, d, sa, da) == d
6645         //       => s == 0
6646         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
6647         //       => colormod is never problematic for these
6648         //   src == GL_SRC_COLOR:
6649         //     s*s + d * dst(s, d, sa, da) == d
6650         //       => s == 0
6651         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
6652         //       => colormod is never problematic for these
6653         //   src == GL_ONE_MINUS_SRC_COLOR:
6654         //     s*(1-s) + d * dst(s, d, sa, da) == d
6655         //       => s == 0 or s == 1
6656         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
6657         //       => colormod is a problem for GL_SRC_COLOR only
6658         //   src == GL_DST_COLOR
6659         //     s*d + d * dst(s, d, sa, da) == d
6660         //       => s == 1
6661         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
6662         //       => colormod is always a problem
6663         //     or
6664         //       => s == 0
6665         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
6666         //       => colormod is never problematic for these
6667         //       => BUT, we do not know s! We must assume it is problematic
6668         //       then... except in GL_ONE case, where we know all invariant
6669         //       cases are fine
6670         //   src == GL_ONE_MINUS_DST_COLOR
6671         //     s*(1-d) + d * dst(s, d, sa, da) == d
6672         //       => s == 0 (1-d is impossible to handle for our desired result)
6673         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
6674         //       => colormod is never problematic for these
6675         //   src == GL_SRC_ALPHA
6676         //     s*sa + d * dst(s, d, sa, da) == d
6677         //       => s == 0, or sa == 0
6678         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
6679         //       => colormod breaks in the case GL_SRC_COLOR only
6680         //   src == GL_ONE_MINUS_SRC_ALPHA
6681         //     s*(1-sa) + d * dst(s, d, sa, da) == d
6682         //       => s == 0, or sa == 1
6683         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
6684         //       => colormod breaks in the case GL_SRC_COLOR only
6685         //   src == GL_DST_ALPHA
6686         //     s*da + d * dst(s, d, sa, da) == d
6687         //       => s == 0
6688         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
6689         //       => colormod is never problematic for these
6690
6691         switch(src)
6692         {
6693                 case GL_ZERO:
6694                 case GL_ONE_MINUS_SRC_COLOR:
6695                 case GL_SRC_ALPHA:
6696                 case GL_ONE_MINUS_SRC_ALPHA:
6697                         if(dst == GL_SRC_COLOR)
6698                                 return false;
6699                         return true;
6700                 case GL_ONE:
6701                 case GL_SRC_COLOR:
6702                 case GL_ONE_MINUS_DST_COLOR:
6703                 case GL_DST_ALPHA:
6704                 case GL_ONE_MINUS_DST_ALPHA:
6705                         return true;
6706                 case GL_DST_COLOR:
6707                         if(dst == GL_ONE)
6708                                 return true;
6709                         return false;
6710                 default:
6711                         return false;
6712         }
6713 }
6714 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane)
6715 {
6716         // select a permutation of the lighting shader appropriate to this
6717         // combination of texture, entity, light source, and fogging, only use the
6718         // minimum features necessary to avoid wasting rendering time in the
6719         // fragment shader on features that are not being used
6720         unsigned int permutation = 0;
6721         unsigned int mode = 0;
6722         qboolean allow_colormod;
6723         static float dummy_colormod[3] = {1, 1, 1};
6724         float *colormod = rsurface.colormod;
6725         float m16f[16];
6726         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
6727         if (rsurfacepass == RSURFPASS_BACKGROUND)
6728         {
6729                 // distorted background
6730                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
6731                 {
6732                         mode = SHADERMODE_WATER;
6733                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
6734                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
6735                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
6736                         {
6737                                 // this is the right thing to do for wateralpha
6738                                 GL_BlendFunc(GL_ONE, GL_ZERO);
6739                                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
6740                         }
6741                         else
6742                         {
6743                                 // this is the right thing to do for entity alpha
6744                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6745                                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6746                         }
6747                 }
6748                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
6749                 {
6750                         mode = SHADERMODE_REFRACTION;
6751                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6752                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6753                 }
6754                 else
6755                 {
6756                         mode = SHADERMODE_GENERIC;
6757                         permutation |= SHADERPERMUTATION_DIFFUSE;
6758                         GL_BlendFunc(GL_ONE, GL_ZERO);
6759                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
6760                 }
6761                 GL_AlphaTest(false);
6762         }
6763         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
6764         {
6765                 if (r_glsl_offsetmapping.integer)
6766                 {
6767                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
6768                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
6769                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
6770                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
6771                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
6772                         {
6773                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
6774                                 if (r_glsl_offsetmapping_reliefmapping.integer)
6775                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
6776                         }
6777                 }
6778                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
6779                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
6780                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6781                         permutation |= SHADERPERMUTATION_ALPHAKILL;
6782                 // normalmap (deferred prepass), may use alpha test on diffuse
6783                 mode = SHADERMODE_DEFERREDGEOMETRY;
6784                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
6785                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
6786                 GL_AlphaTest(false);
6787                 GL_BlendFunc(GL_ONE, GL_ZERO);
6788                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
6789         }
6790         else if (rsurfacepass == RSURFPASS_RTLIGHT)
6791         {
6792                 if (r_glsl_offsetmapping.integer)
6793                 {
6794                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
6795                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
6796                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
6797                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
6798                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
6799                         {
6800                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
6801                                 if (r_glsl_offsetmapping_reliefmapping.integer)
6802                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
6803                         }
6804                 }
6805                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
6806                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
6807                 // light source
6808                 mode = SHADERMODE_LIGHTSOURCE;
6809                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
6810                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
6811                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
6812                         permutation |= SHADERPERMUTATION_CUBEFILTER;
6813                 if (diffusescale > 0)
6814                         permutation |= SHADERPERMUTATION_DIFFUSE;
6815                 if (specularscale > 0)
6816                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6817                 if (r_refdef.fogenabled)
6818                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
6819                 if (rsurface.texture->colormapping)
6820                         permutation |= SHADERPERMUTATION_COLORMAPPING;
6821                 if (r_shadow_usingshadowmap2d)
6822                 {
6823                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6824                         if(r_shadow_shadowmapvsdct)
6825                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6826
6827                         if (r_shadow_shadowmapsampler)
6828                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6829                         if (r_shadow_shadowmappcf > 1)
6830                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6831                         else if (r_shadow_shadowmappcf)
6832                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6833                 }
6834                 if (rsurface.texture->reflectmasktexture)
6835                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
6836                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6837                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6838                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
6839         }
6840         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6841         {
6842                 if (r_glsl_offsetmapping.integer)
6843                 {
6844                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
6845                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
6846                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
6847                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
6848                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
6849                         {
6850                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
6851                                 if (r_glsl_offsetmapping_reliefmapping.integer)
6852                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
6853                         }
6854                 }
6855                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
6856                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
6857                 // unshaded geometry (fullbright or ambient model lighting)
6858                 mode = SHADERMODE_FLATCOLOR;
6859                 ambientscale = diffusescale = specularscale = 0;
6860                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
6861                         permutation |= SHADERPERMUTATION_GLOW;
6862                 if (r_refdef.fogenabled)
6863                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
6864                 if (rsurface.texture->colormapping)
6865                         permutation |= SHADERPERMUTATION_COLORMAPPING;
6866                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
6867                 {
6868                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
6869                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6870
6871                         if (r_shadow_shadowmapsampler)
6872                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6873                         if (r_shadow_shadowmappcf > 1)
6874                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6875                         else if (r_shadow_shadowmappcf)
6876                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6877                 }
6878                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
6879                         permutation |= SHADERPERMUTATION_REFLECTION;
6880                 if (rsurface.texture->reflectmasktexture)
6881                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
6882                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6883                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6884                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6885         }
6886         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
6887         {
6888                 if (r_glsl_offsetmapping.integer)
6889                 {
6890                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
6891                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
6892                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
6893                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
6894                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
6895                         {
6896                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
6897                                 if (r_glsl_offsetmapping_reliefmapping.integer)
6898                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
6899                         }
6900                 }
6901                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
6902                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
6903                 // directional model lighting
6904                 mode = SHADERMODE_LIGHTDIRECTION;
6905                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
6906                         permutation |= SHADERPERMUTATION_GLOW;
6907                 permutation |= SHADERPERMUTATION_DIFFUSE;
6908                 if (specularscale > 0)
6909                         permutation |= SHADERPERMUTATION_SPECULAR;
6910                 if (r_refdef.fogenabled)
6911                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
6912                 if (rsurface.texture->colormapping)
6913                         permutation |= SHADERPERMUTATION_COLORMAPPING;
6914                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
6915                 {
6916                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
6917                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6918
6919                         if (r_shadow_shadowmapsampler)
6920                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6921                         if (r_shadow_shadowmappcf > 1)
6922                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6923                         else if (r_shadow_shadowmappcf)
6924                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6925                 }
6926                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
6927                         permutation |= SHADERPERMUTATION_REFLECTION;
6928                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
6929                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
6930                 if (rsurface.texture->reflectmasktexture)
6931                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
6932                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6933                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6934                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6935         }
6936         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6937         {
6938                 if (r_glsl_offsetmapping.integer)
6939                 {
6940                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
6941                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
6942                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
6943                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
6944                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
6945                         {
6946                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
6947                                 if (r_glsl_offsetmapping_reliefmapping.integer)
6948                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
6949                         }
6950                 }
6951                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
6952                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
6953                 // ambient model lighting
6954                 mode = SHADERMODE_LIGHTDIRECTION;
6955                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
6956                         permutation |= SHADERPERMUTATION_GLOW;
6957                 if (r_refdef.fogenabled)
6958                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
6959                 if (rsurface.texture->colormapping)
6960                         permutation |= SHADERPERMUTATION_COLORMAPPING;
6961                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
6962                 {
6963                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
6964                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6965
6966                         if (r_shadow_shadowmapsampler)
6967                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6968                         if (r_shadow_shadowmappcf > 1)
6969                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6970                         else if (r_shadow_shadowmappcf)
6971                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6972                 }
6973                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
6974                         permutation |= SHADERPERMUTATION_REFLECTION;
6975                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
6976                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
6977                 if (rsurface.texture->reflectmasktexture)
6978                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
6979                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6980                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6981                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6982         }
6983         else
6984         {
6985                 if (r_glsl_offsetmapping.integer)
6986                 {
6987                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
6988                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
6989                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
6990                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
6991                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
6992                         {
6993                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
6994                                 if (r_glsl_offsetmapping_reliefmapping.integer)
6995                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
6996                         }
6997                 }
6998                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
6999                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
7000                 // lightmapped wall
7001                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
7002                         permutation |= SHADERPERMUTATION_GLOW;
7003                 if (r_refdef.fogenabled)
7004                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
7005                 if (rsurface.texture->colormapping)
7006                         permutation |= SHADERPERMUTATION_COLORMAPPING;
7007                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
7008                 {
7009                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
7010                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
7011
7012                         if (r_shadow_shadowmapsampler)
7013                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
7014                         if (r_shadow_shadowmappcf > 1)
7015                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
7016                         else if (r_shadow_shadowmappcf)
7017                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
7018                 }
7019                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
7020                         permutation |= SHADERPERMUTATION_REFLECTION;
7021                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
7022                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
7023                 if (rsurface.texture->reflectmasktexture)
7024                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
7025                 if (FAKELIGHT_ENABLED)
7026                 {
7027                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
7028                         mode = SHADERMODE_FAKELIGHT;
7029                         permutation |= SHADERPERMUTATION_DIFFUSE;
7030                         if (specularscale > 0)
7031                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
7032                 }
7033                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
7034                 {
7035                         // deluxemapping (light direction texture)
7036                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
7037                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
7038                         else
7039                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
7040                         permutation |= SHADERPERMUTATION_DIFFUSE;
7041                         if (specularscale > 0)
7042                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
7043                 }
7044                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
7045                 {
7046                         // fake deluxemapping (uniform light direction in tangentspace)
7047                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
7048                         permutation |= SHADERPERMUTATION_DIFFUSE;
7049                         if (specularscale > 0)
7050                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
7051                 }
7052                 else if (rsurface.uselightmaptexture)
7053                 {
7054                         // ordinary lightmapping (q1bsp, q3bsp)
7055                         mode = SHADERMODE_LIGHTMAP;
7056                 }
7057                 else
7058                 {
7059                         // ordinary vertex coloring (q3bsp)
7060                         mode = SHADERMODE_VERTEXCOLOR;
7061                 }
7062                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7063                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7064                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7065         }
7066         if(!allow_colormod)
7067                 colormod = dummy_colormod;
7068         switch(vid.renderpath)
7069         {
7070         case RENDERPATH_D3D9:
7071 #ifdef SUPPORTD3D
7072                 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
7073                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
7074                 R_SetupShader_SetPermutationHLSL(mode, permutation);
7075                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
7076                 if (mode == SHADERMODE_LIGHTSOURCE)
7077                 {
7078                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
7079                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
7080                 }
7081                 else
7082                 {
7083                         if (mode == SHADERMODE_LIGHTDIRECTION)
7084                         {
7085                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
7086                         }
7087                 }
7088                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
7089                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
7090                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
7091                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
7092                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
7093
7094                 if (mode == SHADERMODE_LIGHTSOURCE)
7095                 {
7096                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
7097                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
7098                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
7099                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
7100                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
7101
7102                         // additive passes are only darkened by fog, not tinted
7103                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
7104                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
7105                 }
7106                 else
7107                 {
7108                         if (mode == SHADERMODE_FLATCOLOR)
7109                         {
7110                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
7111                         }
7112                         else if (mode == SHADERMODE_LIGHTDIRECTION)
7113                         {
7114                                 hlslPSSetParameter3f(D3DPSREGISTER_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]);
7115                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
7116                                 hlslPSSetParameter3f(D3DPSREGISTER_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);
7117                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
7118                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
7119                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
7120                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
7121                         }
7122                         else
7123                         {
7124                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
7125                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
7126                                 hlslPSSetParameter3f(D3DPSREGISTER_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);
7127                                 hlslPSSetParameter3f(D3DPSREGISTER_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);
7128                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
7129                         }
7130                         // additive passes are only darkened by fog, not tinted
7131                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7132                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
7133                         else
7134                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
7135                         hlslPSSetParameter4f(D3DPSREGISTER_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);
7136                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
7137                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
7138                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
7139                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
7140                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
7141                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
7142                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
7143                         if (mode == SHADERMODE_WATER)
7144                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
7145                 }
7146                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
7147                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
7148                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
7149                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
7150                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
7151                 if (rsurface.texture->pantstexture)
7152                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
7153                 else
7154                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
7155                 if (rsurface.texture->shirttexture)
7156                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
7157                 else
7158                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
7159                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
7160                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
7161                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
7162                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
7163                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
7164                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
7165                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
7166
7167                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
7168                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
7169                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
7170                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
7171                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
7172                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
7173                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
7174                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
7175                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
7176                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
7177                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
7178                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
7179                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
7180                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
7181                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
7182                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
7183                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
7184                 if (rsurfacepass == RSURFPASS_BACKGROUND)
7185                 {
7186                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
7187                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
7188                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
7189                 }
7190                 else
7191                 {
7192                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
7193                 }
7194 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
7195 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
7196                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
7197                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
7198                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
7199                 {
7200                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
7201                         if (rsurface.rtlight)
7202                         {
7203                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
7204                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
7205                         }
7206                 }
7207 #endif
7208                 break;
7209         case RENDERPATH_D3D10:
7210                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7211                 break;
7212         case RENDERPATH_D3D11:
7213                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7214                 break;
7215         case RENDERPATH_GL20:
7216         case RENDERPATH_GLES2:
7217                 if (!vid.useinterleavedarrays)
7218                 {
7219                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
7220                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
7221                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
7222                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
7223                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
7224                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
7225                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
7226                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
7227                 }
7228                 else
7229                 {
7230                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
7231                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
7232                 }
7233                 R_SetupShader_SetPermutationGLSL(mode, permutation);
7234                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
7235                 if (mode == SHADERMODE_LIGHTSOURCE)
7236                 {
7237                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
7238                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
7239                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
7240                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
7241                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
7242                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
7243         
7244                         // additive passes are only darkened by fog, not tinted
7245                         if (r_glsl_permutation->loc_FogColor >= 0)
7246                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
7247                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
7248                 }
7249                 else
7250                 {
7251                         if (mode == SHADERMODE_FLATCOLOR)
7252                         {
7253                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
7254                         }
7255                         else if (mode == SHADERMODE_LIGHTDIRECTION)
7256                         {
7257                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(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]);
7258                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
7259                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(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);
7260                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(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);
7261                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
7262                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(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]);
7263                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
7264                         }
7265                         else
7266                         {
7267                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
7268                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
7269                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(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);
7270                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(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);
7271                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
7272                         }
7273                         // additive passes are only darkened by fog, not tinted
7274                         if (r_glsl_permutation->loc_FogColor >= 0)
7275                         {
7276                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7277                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
7278                                 else
7279                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
7280                         }
7281                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(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);
7282                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
7283                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
7284                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(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]);
7285                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(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]);
7286                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
7287                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
7288                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
7289                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
7290                 }
7291                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
7292                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
7293                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
7294                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
7295                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(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]);
7296
7297                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
7298                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(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));
7299                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
7300                 if (r_glsl_permutation->loc_Color_Pants >= 0)
7301                 {
7302                         if (rsurface.texture->pantstexture)
7303                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
7304                         else
7305                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
7306                 }
7307                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
7308                 {
7309                         if (rsurface.texture->shirttexture)
7310                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
7311                         else
7312                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
7313                 }
7314                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
7315                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
7316                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
7317                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
7318                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
7319                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
7320                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7321
7322                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
7323                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
7324                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
7325                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
7326                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
7327                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
7328                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
7329                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
7330                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
7331                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
7332                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
7333                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
7334                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
7335                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
7336                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
7337                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
7338                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
7339                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
7340                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
7341                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
7342                 if (rsurfacepass == RSURFPASS_BACKGROUND)
7343                 {
7344                         if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
7345                         if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
7346                         if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
7347                 }
7348                 else
7349                 {
7350                         if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
7351                 }
7352                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
7353                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
7354                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
7355                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
7356                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
7357                 {
7358                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
7359                         if (rsurface.rtlight)
7360                         {
7361                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
7362                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
7363                         }
7364                 }
7365                 CHECKGLERROR
7366                 break;
7367         case RENDERPATH_CGGL:
7368 #ifdef SUPPORTCG
7369                 if (!vid.useinterleavedarrays)
7370                 {
7371                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
7372                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
7373                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
7374                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
7375                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
7376                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
7377                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
7378                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
7379                 }
7380                 else
7381                 {
7382                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
7383                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
7384                 }
7385                 R_SetupShader_SetPermutationCG(mode, permutation);
7386                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
7387                 if (mode == SHADERMODE_LIGHTSOURCE)
7388                 {
7389                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
7390                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
7391                 }
7392                 else
7393                 {
7394                         if (mode == SHADERMODE_LIGHTDIRECTION)
7395                         {
7396                                 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
7397                         }
7398                 }
7399                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
7400                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
7401                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
7402                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
7403                 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
7404                 CHECKGLERROR
7405
7406                 if (mode == SHADERMODE_LIGHTSOURCE)
7407                 {
7408                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
7409                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
7410                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
7411                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
7412                         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
7413
7414                         // additive passes are only darkened by fog, not tinted
7415                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
7416                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
7417                 }
7418                 else
7419                 {
7420                         if (mode == SHADERMODE_FLATCOLOR)
7421                         {
7422                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
7423                         }
7424                         else if (mode == SHADERMODE_LIGHTDIRECTION)
7425                         {
7426                                 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
7427                                 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
7428                                 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
7429                                 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
7430                                 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
7431                                 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
7432                                 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
7433                         }
7434                         else
7435                         {
7436                                 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
7437                                 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
7438                                 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
7439                                 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
7440                                 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
7441                         }
7442                         // additive passes are only darkened by fog, not tinted
7443                         if (r_cg_permutation->fp_FogColor)
7444                         {
7445                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7446                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
7447                                 else
7448                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
7449                                 CHECKCGERROR
7450                         }
7451                         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
7452                         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
7453                         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
7454                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4f(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
7455                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4f(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
7456                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
7457                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
7458                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
7459                         if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
7460                 }
7461                 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
7462                 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
7463                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
7464                 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
7465                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
7466                 if (r_cg_permutation->fp_Color_Pants)
7467                 {
7468                         if (rsurface.texture->pantstexture)
7469                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
7470                         else
7471                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
7472                         CHECKCGERROR
7473                 }
7474                 if (r_cg_permutation->fp_Color_Shirt)
7475                 {
7476                         if (rsurface.texture->shirttexture)
7477                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
7478                         else
7479                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
7480                         CHECKCGERROR
7481                 }
7482                 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
7483                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
7484                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
7485                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
7486                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
7487                 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
7488                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7489
7490         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
7491         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
7492         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
7493                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
7494                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
7495                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
7496                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
7497                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
7498                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
7499                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
7500                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
7501                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
7502                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
7503                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
7504                 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
7505                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
7506                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
7507                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
7508                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
7509                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
7510                 if (rsurfacepass == RSURFPASS_BACKGROUND)
7511                 {
7512                         if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);CHECKCGERROR
7513                         else if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);CHECKCGERROR
7514                         if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);CHECKCGERROR
7515                 }
7516                 else
7517                 {
7518                         if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);CHECKCGERROR
7519                 }
7520                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
7521                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
7522                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
7523                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
7524                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
7525                 {
7526                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
7527                         if (rsurface.rtlight)
7528                         {
7529                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
7530                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
7531                         }
7532                 }
7533
7534                 CHECKGLERROR
7535 #endif
7536                 break;
7537         case RENDERPATH_GL13:
7538         case RENDERPATH_GL11:
7539                 break;
7540         case RENDERPATH_SOFT:
7541                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
7542                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
7543                 R_SetupShader_SetPermutationSoft(mode, permutation);
7544                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
7545                 if (mode == SHADERMODE_LIGHTSOURCE)
7546                 {
7547                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
7548                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
7549                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
7550                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
7551                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
7552                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
7553         
7554                         // additive passes are only darkened by fog, not tinted
7555                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
7556                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
7557                 }
7558                 else
7559                 {
7560                         if (mode == SHADERMODE_FLATCOLOR)
7561                         {
7562                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
7563                         }
7564                         else if (mode == SHADERMODE_LIGHTDIRECTION)
7565                         {
7566                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_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]);
7567                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
7568                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_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);
7569                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
7570                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
7571                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_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]);
7572                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
7573                         }
7574                         else
7575                         {
7576                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
7577                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
7578                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_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);
7579                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_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);
7580                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
7581                         }
7582                         // additive passes are only darkened by fog, not tinted
7583                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7584                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
7585                         else
7586                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
7587                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_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);
7588                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
7589                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
7590                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
7591                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
7592                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
7593                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
7594                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
7595                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
7596                 }
7597                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
7598                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
7599                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
7600                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
7601                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
7602
7603                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
7604                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
7605                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
7606                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
7607                 {
7608                         if (rsurface.texture->pantstexture)
7609                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
7610                         else
7611                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
7612                 }
7613                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
7614                 {
7615                         if (rsurface.texture->shirttexture)
7616                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
7617                         else
7618                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
7619                 }
7620                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
7621                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
7622                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
7623                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
7624                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
7625                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
7626                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7627
7628                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
7629                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
7630                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
7631                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
7632                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
7633                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
7634                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
7635                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
7636                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
7637                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
7638                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
7639                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
7640                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
7641                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
7642                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
7643                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
7644                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
7645                 if (rsurfacepass == RSURFPASS_BACKGROUND)
7646                 {
7647                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
7648                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
7649                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
7650                 }
7651                 else
7652                 {
7653                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
7654                 }
7655 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
7656 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
7657                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
7658                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
7659                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
7660                 {
7661                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
7662                         if (rsurface.rtlight)
7663                         {
7664                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
7665                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
7666                         }
7667                 }
7668                 break;
7669         }
7670 }
7671
7672 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
7673 {
7674         // select a permutation of the lighting shader appropriate to this
7675         // combination of texture, entity, light source, and fogging, only use the
7676         // minimum features necessary to avoid wasting rendering time in the
7677         // fragment shader on features that are not being used
7678         unsigned int permutation = 0;
7679         unsigned int mode = 0;
7680         const float *lightcolorbase = rtlight->currentcolor;
7681         float ambientscale = rtlight->ambientscale;
7682         float diffusescale = rtlight->diffusescale;
7683         float specularscale = rtlight->specularscale;
7684         // this is the location of the light in view space
7685         vec3_t viewlightorigin;
7686         // this transforms from view space (camera) to light space (cubemap)
7687         matrix4x4_t viewtolight;
7688         matrix4x4_t lighttoview;
7689         float viewtolight16f[16];
7690         float range = 1.0f / r_shadow_deferred_8bitrange.value;
7691         // light source
7692         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
7693         if (rtlight->currentcubemap != r_texture_whitecube)
7694                 permutation |= SHADERPERMUTATION_CUBEFILTER;
7695         if (diffusescale > 0)
7696                 permutation |= SHADERPERMUTATION_DIFFUSE;
7697         if (specularscale > 0)
7698                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
7699         if (r_shadow_usingshadowmap2d)
7700         {
7701                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
7702                 if (r_shadow_shadowmapvsdct)
7703                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
7704
7705                 if (r_shadow_shadowmapsampler)
7706                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
7707                 if (r_shadow_shadowmappcf > 1)
7708                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
7709                 else if (r_shadow_shadowmappcf)
7710                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
7711         }
7712         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
7713         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
7714         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
7715         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
7716         switch(vid.renderpath)
7717         {
7718         case RENDERPATH_D3D9:
7719 #ifdef SUPPORTD3D
7720                 R_SetupShader_SetPermutationHLSL(mode, permutation);
7721                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
7722                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
7723                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
7724                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
7725                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
7726                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
7727                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
7728                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
7729                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
7730                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
7731
7732                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
7733                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
7734                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
7735                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
7736                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
7737                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
7738 #endif
7739                 break;
7740         case RENDERPATH_D3D10:
7741                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7742                 break;
7743         case RENDERPATH_D3D11:
7744                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7745                 break;
7746         case RENDERPATH_GL20:
7747         case RENDERPATH_GLES2:
7748                 R_SetupShader_SetPermutationGLSL(mode, permutation);
7749                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
7750                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
7751                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
7752                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
7753                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
7754                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
7755                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       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]);
7756                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1f(       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));
7757                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2f(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
7758                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
7759
7760                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
7761                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
7762                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
7763                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
7764                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
7765                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
7766                 break;
7767         case RENDERPATH_CGGL:
7768 #ifdef SUPPORTCG
7769                 R_SetupShader_SetPermutationCG(mode, permutation);
7770                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
7771                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
7772                 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
7773                 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
7774                 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
7775                 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
7776                 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
7777                 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
7778                 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
7779                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7780
7781                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
7782                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
7783                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
7784                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
7785                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
7786                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
7787 #endif
7788                 break;
7789         case RENDERPATH_GL13:
7790         case RENDERPATH_GL11:
7791                 break;
7792         case RENDERPATH_SOFT:
7793                 R_SetupShader_SetPermutationGLSL(mode, permutation);
7794                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
7795                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
7796                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
7797                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
7798                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
7799                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
7800                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
7801                 DPSOFTRAST_Uniform1f(       DPSOFTRAST_UNIFORM_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
7802                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
7803                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7804
7805                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
7806                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
7807                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
7808                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
7809                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
7810                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
7811                 break;
7812         }
7813 }
7814
7815 #define SKINFRAME_HASH 1024
7816
7817 typedef struct
7818 {
7819         int loadsequence; // incremented each level change
7820         memexpandablearray_t array;
7821         skinframe_t *hash[SKINFRAME_HASH];
7822 }
7823 r_skinframe_t;
7824 r_skinframe_t r_skinframe;
7825
7826 void R_SkinFrame_PrepareForPurge(void)
7827 {
7828         r_skinframe.loadsequence++;
7829         // wrap it without hitting zero
7830         if (r_skinframe.loadsequence >= 200)
7831                 r_skinframe.loadsequence = 1;
7832 }
7833
7834 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
7835 {
7836         if (!skinframe)
7837                 return;
7838         // mark the skinframe as used for the purging code
7839         skinframe->loadsequence = r_skinframe.loadsequence;
7840 }
7841
7842 void R_SkinFrame_Purge(void)
7843 {
7844         int i;
7845         skinframe_t *s;
7846         for (i = 0;i < SKINFRAME_HASH;i++)
7847         {
7848                 for (s = r_skinframe.hash[i];s;s = s->next)
7849                 {
7850                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
7851                         {
7852                                 if (s->merged == s->base)
7853                                         s->merged = NULL;
7854                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
7855                                 R_PurgeTexture(s->stain );s->stain  = NULL;
7856                                 R_PurgeTexture(s->merged);s->merged = NULL;
7857                                 R_PurgeTexture(s->base  );s->base   = NULL;
7858                                 R_PurgeTexture(s->pants );s->pants  = NULL;
7859                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
7860                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
7861                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
7862                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
7863                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
7864                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
7865                                 s->loadsequence = 0;
7866                         }
7867                 }
7868         }
7869 }
7870
7871 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
7872         skinframe_t *item;
7873         char basename[MAX_QPATH];
7874
7875         Image_StripImageExtension(name, basename, sizeof(basename));
7876
7877         if( last == NULL ) {
7878                 int hashindex;
7879                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
7880                 item = r_skinframe.hash[hashindex];
7881         } else {
7882                 item = last->next;
7883         }
7884
7885         // linearly search through the hash bucket
7886         for( ; item ; item = item->next ) {
7887                 if( !strcmp( item->basename, basename ) ) {
7888                         return item;
7889                 }
7890         }
7891         return NULL;
7892 }
7893
7894 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
7895 {
7896         skinframe_t *item;
7897         int hashindex;
7898         char basename[MAX_QPATH];
7899
7900         Image_StripImageExtension(name, basename, sizeof(basename));
7901
7902         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
7903         for (item = r_skinframe.hash[hashindex];item;item = item->next)
7904                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
7905                         break;
7906
7907         if (!item) {
7908                 rtexture_t *dyntexture;
7909                 // check whether its a dynamic texture
7910                 dyntexture = CL_GetDynTexture( basename );
7911                 if (!add && !dyntexture)
7912                         return NULL;
7913                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
7914                 memset(item, 0, sizeof(*item));
7915                 strlcpy(item->basename, basename, sizeof(item->basename));
7916                 item->base = dyntexture; // either NULL or dyntexture handle
7917                 item->textureflags = textureflags;
7918                 item->comparewidth = comparewidth;
7919                 item->compareheight = compareheight;
7920                 item->comparecrc = comparecrc;
7921                 item->next = r_skinframe.hash[hashindex];
7922                 r_skinframe.hash[hashindex] = item;
7923         }
7924         else if( item->base == NULL )
7925         {
7926                 rtexture_t *dyntexture;
7927                 // check whether its a dynamic texture
7928                 // 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]
7929                 dyntexture = CL_GetDynTexture( basename );
7930                 item->base = dyntexture; // either NULL or dyntexture handle
7931         }
7932
7933         R_SkinFrame_MarkUsed(item);
7934         return item;
7935 }
7936
7937 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
7938         { \
7939                 unsigned long long avgcolor[5], wsum; \
7940                 int pix, comp, w; \
7941                 avgcolor[0] = 0; \
7942                 avgcolor[1] = 0; \
7943                 avgcolor[2] = 0; \
7944                 avgcolor[3] = 0; \
7945                 avgcolor[4] = 0; \
7946                 wsum = 0; \
7947                 for(pix = 0; pix < cnt; ++pix) \
7948                 { \
7949                         w = 0; \
7950                         for(comp = 0; comp < 3; ++comp) \
7951                                 w += getpixel; \
7952                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
7953                         { \
7954                                 ++wsum; \
7955                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
7956                                 w = getpixel; \
7957                                 for(comp = 0; comp < 3; ++comp) \
7958                                         avgcolor[comp] += getpixel * w; \
7959                                 avgcolor[3] += w; \
7960                         } \
7961                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
7962                         avgcolor[4] += getpixel; \
7963                 } \
7964                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
7965                         avgcolor[3] = 1; \
7966                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
7967                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
7968                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
7969                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
7970         }
7971
7972 extern cvar_t gl_picmip;
7973 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
7974 {
7975         int j;
7976         unsigned char *pixels;
7977         unsigned char *bumppixels;
7978         unsigned char *basepixels = NULL;
7979         int basepixels_width = 0;
7980         int basepixels_height = 0;
7981         skinframe_t *skinframe;
7982         rtexture_t *ddsbase = NULL;
7983         qboolean ddshasalpha = false;
7984         float ddsavgcolor[4];
7985         char basename[MAX_QPATH];
7986         int miplevel = R_PicmipForFlags(textureflags);
7987         int savemiplevel = miplevel;
7988         int mymiplevel;
7989
7990         if (cls.state == ca_dedicated)
7991                 return NULL;
7992
7993         // return an existing skinframe if already loaded
7994         // if loading of the first image fails, don't make a new skinframe as it
7995         // would cause all future lookups of this to be missing
7996         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7997         if (skinframe && skinframe->base)
7998                 return skinframe;
7999
8000         Image_StripImageExtension(name, basename, sizeof(basename));
8001
8002         // check for DDS texture file first
8003         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
8004         {
8005                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
8006                 if (basepixels == NULL)
8007                         return NULL;
8008         }
8009
8010         // FIXME handle miplevel
8011
8012         if (developer_loading.integer)
8013                 Con_Printf("loading skin \"%s\"\n", name);
8014
8015         // we've got some pixels to store, so really allocate this new texture now
8016         if (!skinframe)
8017                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
8018         skinframe->stain = NULL;
8019         skinframe->merged = NULL;
8020         skinframe->base = NULL;
8021         skinframe->pants = NULL;
8022         skinframe->shirt = NULL;
8023         skinframe->nmap = NULL;
8024         skinframe->gloss = NULL;
8025         skinframe->glow = NULL;
8026         skinframe->fog = NULL;
8027         skinframe->reflect = NULL;
8028         skinframe->hasalpha = false;
8029
8030         if (ddsbase)
8031         {
8032                 skinframe->base = ddsbase;
8033                 skinframe->hasalpha = ddshasalpha;
8034                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
8035                 if (r_loadfog && skinframe->hasalpha)
8036                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
8037                 //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]);
8038         }
8039         else
8040         {
8041                 basepixels_width = image_width;
8042                 basepixels_height = image_height;
8043                 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);
8044                 if (textureflags & TEXF_ALPHA)
8045                 {
8046                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
8047                         {
8048                                 if (basepixels[j] < 255)
8049                                 {
8050                                         skinframe->hasalpha = true;
8051                                         break;
8052                                 }
8053                         }
8054                         if (r_loadfog && skinframe->hasalpha)
8055                         {
8056                                 // has transparent pixels
8057                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
8058                                 for (j = 0;j < image_width * image_height * 4;j += 4)
8059                                 {
8060                                         pixels[j+0] = 255;
8061                                         pixels[j+1] = 255;
8062                                         pixels[j+2] = 255;
8063                                         pixels[j+3] = basepixels[j+3];
8064                                 }
8065                                 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);
8066                                 Mem_Free(pixels);
8067                         }
8068                 }
8069                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
8070                 //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]);
8071                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
8072                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
8073                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
8074                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
8075         }
8076
8077         if (r_loaddds)
8078         {
8079                 mymiplevel = savemiplevel;
8080                 if (r_loadnormalmap)
8081                         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);
8082                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
8083                 if (r_loadgloss)
8084                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
8085                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
8086                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
8087                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
8088         }
8089
8090         // _norm is the name used by tenebrae and has been adopted as standard
8091         if (r_loadnormalmap && skinframe->nmap == NULL)
8092         {
8093                 mymiplevel = savemiplevel;
8094                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
8095                 {
8096                         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);
8097                         Mem_Free(pixels);
8098                         pixels = NULL;
8099                 }
8100                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
8101                 {
8102                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
8103                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
8104                         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);
8105                         Mem_Free(pixels);
8106                         Mem_Free(bumppixels);
8107                 }
8108                 else if (r_shadow_bumpscale_basetexture.value > 0)
8109                 {
8110                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
8111                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
8112                         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);
8113                         Mem_Free(pixels);
8114                 }
8115                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
8116                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
8117         }
8118
8119         // _luma is supported only for tenebrae compatibility
8120         // _glow is the preferred name
8121         mymiplevel = savemiplevel;
8122         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))))
8123         {
8124                 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);
8125                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
8126                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
8127                 Mem_Free(pixels);pixels = NULL;
8128         }
8129
8130         mymiplevel = savemiplevel;
8131         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
8132         {
8133                 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);
8134                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
8135                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
8136                 Mem_Free(pixels);
8137                 pixels = NULL;
8138         }
8139
8140         mymiplevel = savemiplevel;
8141         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
8142         {
8143                 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);
8144                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
8145                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
8146                 Mem_Free(pixels);
8147                 pixels = NULL;
8148         }
8149
8150         mymiplevel = savemiplevel;
8151         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
8152         {
8153                 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);
8154                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
8155                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
8156                 Mem_Free(pixels);
8157                 pixels = NULL;
8158         }
8159
8160         mymiplevel = savemiplevel;
8161         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
8162         {
8163                 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);
8164                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
8165                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
8166                 Mem_Free(pixels);
8167                 pixels = NULL;
8168         }
8169
8170         if (basepixels)
8171                 Mem_Free(basepixels);
8172
8173         return skinframe;
8174 }
8175
8176 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
8177 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
8178 {
8179         int i;
8180         unsigned char *temp1, *temp2;
8181         skinframe_t *skinframe;
8182
8183         if (cls.state == ca_dedicated)
8184                 return NULL;
8185
8186         // if already loaded just return it, otherwise make a new skinframe
8187         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
8188         if (skinframe && skinframe->base)
8189                 return skinframe;
8190
8191         skinframe->stain = NULL;
8192         skinframe->merged = NULL;
8193         skinframe->base = NULL;
8194         skinframe->pants = NULL;
8195         skinframe->shirt = NULL;
8196         skinframe->nmap = NULL;
8197         skinframe->gloss = NULL;
8198         skinframe->glow = NULL;
8199         skinframe->fog = NULL;
8200         skinframe->reflect = NULL;
8201         skinframe->hasalpha = false;
8202
8203         // if no data was provided, then clearly the caller wanted to get a blank skinframe
8204         if (!skindata)
8205                 return NULL;
8206
8207         if (developer_loading.integer)
8208                 Con_Printf("loading 32bit skin \"%s\"\n", name);
8209
8210         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
8211         {
8212                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
8213                 temp2 = temp1 + width * height * 4;
8214                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
8215                 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);
8216                 Mem_Free(temp1);
8217         }
8218         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
8219         if (textureflags & TEXF_ALPHA)
8220         {
8221                 for (i = 3;i < width * height * 4;i += 4)
8222                 {
8223                         if (skindata[i] < 255)
8224                         {
8225                                 skinframe->hasalpha = true;
8226                                 break;
8227                         }
8228                 }
8229                 if (r_loadfog && skinframe->hasalpha)
8230                 {
8231                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
8232                         memcpy(fogpixels, skindata, width * height * 4);
8233                         for (i = 0;i < width * height * 4;i += 4)
8234                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
8235                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
8236                         Mem_Free(fogpixels);
8237                 }
8238         }
8239
8240         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
8241         //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]);
8242
8243         return skinframe;
8244 }
8245
8246 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
8247 {
8248         int i;
8249         int featuresmask;
8250         skinframe_t *skinframe;
8251
8252         if (cls.state == ca_dedicated)
8253                 return NULL;
8254
8255         // if already loaded just return it, otherwise make a new skinframe
8256         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
8257         if (skinframe && skinframe->base)
8258                 return skinframe;
8259
8260         skinframe->stain = NULL;
8261         skinframe->merged = NULL;
8262         skinframe->base = NULL;
8263         skinframe->pants = NULL;
8264         skinframe->shirt = NULL;
8265         skinframe->nmap = NULL;
8266         skinframe->gloss = NULL;
8267         skinframe->glow = NULL;
8268         skinframe->fog = NULL;
8269         skinframe->reflect = NULL;
8270         skinframe->hasalpha = false;
8271
8272         // if no data was provided, then clearly the caller wanted to get a blank skinframe
8273         if (!skindata)
8274                 return NULL;
8275
8276         if (developer_loading.integer)
8277                 Con_Printf("loading quake skin \"%s\"\n", name);
8278
8279         // 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)
8280         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
8281         memcpy(skinframe->qpixels, skindata, width*height);
8282         skinframe->qwidth = width;
8283         skinframe->qheight = height;
8284
8285         featuresmask = 0;
8286         for (i = 0;i < width * height;i++)
8287                 featuresmask |= palette_featureflags[skindata[i]];
8288
8289         skinframe->hasalpha = false;
8290         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
8291         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
8292         skinframe->qgeneratemerged = true;
8293         skinframe->qgeneratebase = skinframe->qhascolormapping;
8294         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
8295
8296         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
8297         //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]);
8298
8299         return skinframe;
8300 }
8301
8302 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
8303 {
8304         int width;
8305         int height;
8306         unsigned char *skindata;
8307
8308         if (!skinframe->qpixels)
8309                 return;
8310
8311         if (!skinframe->qhascolormapping)
8312                 colormapped = false;
8313
8314         if (colormapped)
8315         {
8316                 if (!skinframe->qgeneratebase)
8317                         return;
8318         }
8319         else
8320         {
8321                 if (!skinframe->qgeneratemerged)
8322                         return;
8323         }
8324
8325         width = skinframe->qwidth;
8326         height = skinframe->qheight;
8327         skindata = skinframe->qpixels;
8328
8329         if (skinframe->qgeneratenmap)
8330         {
8331                 unsigned char *temp1, *temp2;
8332                 skinframe->qgeneratenmap = false;
8333                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
8334                 temp2 = temp1 + width * height * 4;
8335                 // use either a custom palette or the quake palette
8336                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
8337                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
8338                 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);
8339                 Mem_Free(temp1);
8340         }
8341
8342         if (skinframe->qgenerateglow)
8343         {
8344                 skinframe->qgenerateglow = false;
8345                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
8346         }
8347
8348         if (colormapped)
8349         {
8350                 skinframe->qgeneratebase = false;
8351                 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);
8352                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
8353                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
8354         }
8355         else
8356         {
8357                 skinframe->qgeneratemerged = false;
8358                 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);
8359         }
8360
8361         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
8362         {
8363                 Mem_Free(skinframe->qpixels);
8364                 skinframe->qpixels = NULL;
8365         }
8366 }
8367
8368 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)
8369 {
8370         int i;
8371         skinframe_t *skinframe;
8372
8373         if (cls.state == ca_dedicated)
8374                 return NULL;
8375
8376         // if already loaded just return it, otherwise make a new skinframe
8377         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
8378         if (skinframe && skinframe->base)
8379                 return skinframe;
8380
8381         skinframe->stain = NULL;
8382         skinframe->merged = NULL;
8383         skinframe->base = NULL;
8384         skinframe->pants = NULL;
8385         skinframe->shirt = NULL;
8386         skinframe->nmap = NULL;
8387         skinframe->gloss = NULL;
8388         skinframe->glow = NULL;
8389         skinframe->fog = NULL;
8390         skinframe->reflect = NULL;
8391         skinframe->hasalpha = false;
8392
8393         // if no data was provided, then clearly the caller wanted to get a blank skinframe
8394         if (!skindata)
8395                 return NULL;
8396
8397         if (developer_loading.integer)
8398                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
8399
8400         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
8401         if (textureflags & TEXF_ALPHA)
8402         {
8403                 for (i = 0;i < width * height;i++)
8404                 {
8405                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
8406                         {
8407                                 skinframe->hasalpha = true;
8408                                 break;
8409                         }
8410                 }
8411                 if (r_loadfog && skinframe->hasalpha)
8412                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
8413         }
8414
8415         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
8416         //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]);
8417
8418         return skinframe;
8419 }
8420
8421 skinframe_t *R_SkinFrame_LoadMissing(void)
8422 {
8423         skinframe_t *skinframe;
8424
8425         if (cls.state == ca_dedicated)
8426                 return NULL;
8427
8428         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
8429         skinframe->stain = NULL;
8430         skinframe->merged = NULL;
8431         skinframe->base = NULL;
8432         skinframe->pants = NULL;
8433         skinframe->shirt = NULL;
8434         skinframe->nmap = NULL;
8435         skinframe->gloss = NULL;
8436         skinframe->glow = NULL;
8437         skinframe->fog = NULL;
8438         skinframe->reflect = NULL;
8439         skinframe->hasalpha = false;
8440
8441         skinframe->avgcolor[0] = rand() / RAND_MAX;
8442         skinframe->avgcolor[1] = rand() / RAND_MAX;
8443         skinframe->avgcolor[2] = rand() / RAND_MAX;
8444         skinframe->avgcolor[3] = 1;
8445
8446         return skinframe;
8447 }
8448
8449 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
8450 typedef struct suffixinfo_s
8451 {
8452         const char *suffix;
8453         qboolean flipx, flipy, flipdiagonal;
8454 }
8455 suffixinfo_t;
8456 static suffixinfo_t suffix[3][6] =
8457 {
8458         {
8459                 {"px",   false, false, false},
8460                 {"nx",   false, false, false},
8461                 {"py",   false, false, false},
8462                 {"ny",   false, false, false},
8463                 {"pz",   false, false, false},
8464                 {"nz",   false, false, false}
8465         },
8466         {
8467                 {"posx", false, false, false},
8468                 {"negx", false, false, false},
8469                 {"posy", false, false, false},
8470                 {"negy", false, false, false},
8471                 {"posz", false, false, false},
8472                 {"negz", false, false, false}
8473         },
8474         {
8475                 {"rt",    true, false,  true},
8476                 {"lf",   false,  true,  true},
8477                 {"ft",    true,  true, false},
8478                 {"bk",   false, false, false},
8479                 {"up",    true, false,  true},
8480                 {"dn",    true, false,  true}
8481         }
8482 };
8483
8484 static int componentorder[4] = {0, 1, 2, 3};
8485
8486 rtexture_t *R_LoadCubemap(const char *basename)
8487 {
8488         int i, j, cubemapsize;
8489         unsigned char *cubemappixels, *image_buffer;
8490         rtexture_t *cubemaptexture;
8491         char name[256];
8492         // must start 0 so the first loadimagepixels has no requested width/height
8493         cubemapsize = 0;
8494         cubemappixels = NULL;
8495         cubemaptexture = NULL;
8496         // keep trying different suffix groups (posx, px, rt) until one loads
8497         for (j = 0;j < 3 && !cubemappixels;j++)
8498         {
8499                 // load the 6 images in the suffix group
8500                 for (i = 0;i < 6;i++)
8501                 {
8502                         // generate an image name based on the base and and suffix
8503                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
8504                         // load it
8505                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
8506                         {
8507                                 // an image loaded, make sure width and height are equal
8508                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
8509                                 {
8510                                         // if this is the first image to load successfully, allocate the cubemap memory
8511                                         if (!cubemappixels && image_width >= 1)
8512                                         {
8513                                                 cubemapsize = image_width;
8514                                                 // note this clears to black, so unavailable sides are black
8515                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
8516                                         }
8517                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
8518                                         if (cubemappixels)
8519                                                 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);
8520                                 }
8521                                 else
8522                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
8523                                 // free the image
8524                                 Mem_Free(image_buffer);
8525                         }
8526                 }
8527         }
8528         // if a cubemap loaded, upload it
8529         if (cubemappixels)
8530         {
8531                 if (developer_loading.integer)
8532                         Con_Printf("loading cubemap \"%s\"\n", basename);
8533
8534                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8535                 Mem_Free(cubemappixels);
8536         }
8537         else
8538         {
8539                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
8540                 if (developer_loading.integer)
8541                 {
8542                         Con_Printf("(tried tried images ");
8543                         for (j = 0;j < 3;j++)
8544                                 for (i = 0;i < 6;i++)
8545                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
8546                         Con_Print(" and was unable to find any of them).\n");
8547                 }
8548         }
8549         return cubemaptexture;
8550 }
8551
8552 rtexture_t *R_GetCubemap(const char *basename)
8553 {
8554         int i;
8555         for (i = 0;i < r_texture_numcubemaps;i++)
8556                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
8557                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
8558         if (i >= MAX_CUBEMAPS)
8559                 return r_texture_whitecube;
8560         r_texture_numcubemaps++;
8561         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
8562         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
8563         return r_texture_cubemaps[i].texture;
8564 }
8565
8566 void R_FreeCubemaps(void)
8567 {
8568         int i;
8569         for (i = 0;i < r_texture_numcubemaps;i++)
8570         {
8571                 if (developer_loading.integer)
8572                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
8573                 if (r_texture_cubemaps[i].texture)
8574                         R_FreeTexture(r_texture_cubemaps[i].texture);
8575         }
8576         r_texture_numcubemaps = 0;
8577 }
8578
8579 void R_Main_FreeViewCache(void)
8580 {
8581         if (r_refdef.viewcache.entityvisible)
8582                 Mem_Free(r_refdef.viewcache.entityvisible);
8583         if (r_refdef.viewcache.world_pvsbits)
8584                 Mem_Free(r_refdef.viewcache.world_pvsbits);
8585         if (r_refdef.viewcache.world_leafvisible)
8586                 Mem_Free(r_refdef.viewcache.world_leafvisible);
8587         if (r_refdef.viewcache.world_surfacevisible)
8588                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
8589         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
8590 }
8591
8592 void R_Main_ResizeViewCache(void)
8593 {
8594         int numentities = r_refdef.scene.numentities;
8595         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
8596         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
8597         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
8598         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
8599         if (r_refdef.viewcache.maxentities < numentities)
8600         {
8601                 r_refdef.viewcache.maxentities = numentities;
8602                 if (r_refdef.viewcache.entityvisible)
8603                         Mem_Free(r_refdef.viewcache.entityvisible);
8604                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
8605         }
8606         if (r_refdef.viewcache.world_numclusters != numclusters)
8607         {
8608                 r_refdef.viewcache.world_numclusters = numclusters;
8609                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
8610                 if (r_refdef.viewcache.world_pvsbits)
8611                         Mem_Free(r_refdef.viewcache.world_pvsbits);
8612                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
8613         }
8614         if (r_refdef.viewcache.world_numleafs != numleafs)
8615         {
8616                 r_refdef.viewcache.world_numleafs = numleafs;
8617                 if (r_refdef.viewcache.world_leafvisible)
8618                         Mem_Free(r_refdef.viewcache.world_leafvisible);
8619                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
8620         }
8621         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
8622         {
8623                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
8624                 if (r_refdef.viewcache.world_surfacevisible)
8625                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
8626                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
8627         }
8628 }
8629
8630 extern rtexture_t *loadingscreentexture;
8631 void gl_main_start(void)
8632 {
8633         loadingscreentexture = NULL;
8634         r_texture_blanknormalmap = NULL;
8635         r_texture_white = NULL;
8636         r_texture_grey128 = NULL;
8637         r_texture_black = NULL;
8638         r_texture_whitecube = NULL;
8639         r_texture_normalizationcube = NULL;
8640         r_texture_fogattenuation = NULL;
8641         r_texture_fogheighttexture = NULL;
8642         r_texture_gammaramps = NULL;
8643         r_texture_numcubemaps = 0;
8644
8645         r_loaddds = r_texture_dds_load.integer != 0;
8646         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
8647
8648         switch(vid.renderpath)
8649         {
8650         case RENDERPATH_GL20:
8651         case RENDERPATH_CGGL:
8652         case RENDERPATH_D3D9:
8653         case RENDERPATH_D3D10:
8654         case RENDERPATH_D3D11:
8655         case RENDERPATH_SOFT:
8656                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
8657                 Cvar_SetValueQuick(&gl_combine, 1);
8658                 Cvar_SetValueQuick(&r_glsl, 1);
8659                 r_loadnormalmap = true;
8660                 r_loadgloss = true;
8661                 r_loadfog = false;
8662                 break;
8663         case RENDERPATH_GL13:
8664                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
8665                 Cvar_SetValueQuick(&gl_combine, 1);
8666                 Cvar_SetValueQuick(&r_glsl, 0);
8667                 r_loadnormalmap = false;
8668                 r_loadgloss = false;
8669                 r_loadfog = true;
8670                 break;
8671         case RENDERPATH_GL11:
8672                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
8673                 Cvar_SetValueQuick(&gl_combine, 0);
8674                 Cvar_SetValueQuick(&r_glsl, 0);
8675                 r_loadnormalmap = false;
8676                 r_loadgloss = false;
8677                 r_loadfog = true;
8678                 break;
8679         case RENDERPATH_GLES2:
8680                 Cvar_SetValueQuick(&r_textureunits, 1);
8681                 Cvar_SetValueQuick(&gl_combine, 1);
8682                 Cvar_SetValueQuick(&r_glsl, 1);
8683                 r_loadnormalmap = true;
8684                 r_loadgloss = false;
8685                 r_loadfog = false;
8686                 break;
8687         }
8688
8689         R_AnimCache_Free();
8690         R_FrameData_Reset();
8691
8692         r_numqueries = 0;
8693         r_maxqueries = 0;
8694         memset(r_queries, 0, sizeof(r_queries));
8695
8696         r_qwskincache = NULL;
8697         r_qwskincache_size = 0;
8698
8699         // set up r_skinframe loading system for textures
8700         memset(&r_skinframe, 0, sizeof(r_skinframe));
8701         r_skinframe.loadsequence = 1;
8702         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
8703
8704         r_main_texturepool = R_AllocTexturePool();
8705         R_BuildBlankTextures();
8706         R_BuildNoTexture();
8707         if (vid.support.arb_texture_cube_map)
8708         {
8709                 R_BuildWhiteCube();
8710                 R_BuildNormalizationCube();
8711         }
8712         r_texture_fogattenuation = NULL;
8713         r_texture_fogheighttexture = NULL;
8714         r_texture_gammaramps = NULL;
8715         //r_texture_fogintensity = NULL;
8716         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
8717         memset(&r_waterstate, 0, sizeof(r_waterstate));
8718         r_glsl_permutation = NULL;
8719         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
8720         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
8721         glslshaderstring = NULL;
8722 #ifdef SUPPORTCG
8723         r_cg_permutation = NULL;
8724         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
8725         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
8726         cgshaderstring = NULL;
8727 #endif
8728 #ifdef SUPPORTD3D
8729         r_hlsl_permutation = NULL;
8730         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
8731         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
8732         hlslshaderstring = NULL;
8733 #endif
8734         memset(&r_svbsp, 0, sizeof (r_svbsp));
8735
8736         r_refdef.fogmasktable_density = 0;
8737 }
8738
8739 void gl_main_shutdown(void)
8740 {
8741         R_AnimCache_Free();
8742         R_FrameData_Reset();
8743
8744         R_Main_FreeViewCache();
8745
8746         switch(vid.renderpath)
8747         {
8748         case RENDERPATH_GL11:
8749         case RENDERPATH_GL13:
8750         case RENDERPATH_GL20:
8751         case RENDERPATH_CGGL:
8752                 if (r_maxqueries)
8753                         qglDeleteQueriesARB(r_maxqueries, r_queries);
8754                 break;
8755         case RENDERPATH_D3D9:
8756                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8757                 break;
8758         case RENDERPATH_D3D10:
8759                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8760                 break;
8761         case RENDERPATH_D3D11:
8762                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8763                 break;
8764         case RENDERPATH_SOFT:
8765                 break;
8766         case RENDERPATH_GLES2:
8767                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8768                 break;
8769         }
8770
8771         r_numqueries = 0;
8772         r_maxqueries = 0;
8773         memset(r_queries, 0, sizeof(r_queries));
8774
8775         r_qwskincache = NULL;
8776         r_qwskincache_size = 0;
8777
8778         // clear out the r_skinframe state
8779         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
8780         memset(&r_skinframe, 0, sizeof(r_skinframe));
8781
8782         if (r_svbsp.nodes)
8783                 Mem_Free(r_svbsp.nodes);
8784         memset(&r_svbsp, 0, sizeof (r_svbsp));
8785         R_FreeTexturePool(&r_main_texturepool);
8786         loadingscreentexture = NULL;
8787         r_texture_blanknormalmap = NULL;
8788         r_texture_white = NULL;
8789         r_texture_grey128 = NULL;
8790         r_texture_black = NULL;
8791         r_texture_whitecube = NULL;
8792         r_texture_normalizationcube = NULL;
8793         r_texture_fogattenuation = NULL;
8794         r_texture_fogheighttexture = NULL;
8795         r_texture_gammaramps = NULL;
8796         r_texture_numcubemaps = 0;
8797         //r_texture_fogintensity = NULL;
8798         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
8799         memset(&r_waterstate, 0, sizeof(r_waterstate));
8800         R_GLSL_Restart_f();
8801
8802         r_glsl_permutation = NULL;
8803         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
8804         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
8805         glslshaderstring = NULL;
8806 #ifdef SUPPORTCG
8807         r_cg_permutation = NULL;
8808         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
8809         Mem_ExpandableArray_FreeArray(&r_cg_permutationarray);
8810         cgshaderstring = NULL;
8811 #endif
8812 #ifdef SUPPORTD3D
8813         r_hlsl_permutation = NULL;
8814         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
8815         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
8816         hlslshaderstring = NULL;
8817 #endif
8818 }
8819
8820 extern void CL_ParseEntityLump(char *entitystring);
8821 void gl_main_newmap(void)
8822 {
8823         // FIXME: move this code to client
8824         char *entities, entname[MAX_QPATH];
8825         if (r_qwskincache)
8826                 Mem_Free(r_qwskincache);
8827         r_qwskincache = NULL;
8828         r_qwskincache_size = 0;
8829         if (cl.worldmodel)
8830         {
8831                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
8832                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
8833                 {
8834                         CL_ParseEntityLump(entities);
8835                         Mem_Free(entities);
8836                         return;
8837                 }
8838                 if (cl.worldmodel->brush.entities)
8839                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
8840         }
8841         R_Main_FreeViewCache();
8842
8843         R_FrameData_Reset();
8844 }
8845
8846 void GL_Main_Init(void)
8847 {
8848         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
8849
8850         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
8851         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
8852         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
8853         if (gamemode == GAME_NEHAHRA)
8854         {
8855                 Cvar_RegisterVariable (&gl_fogenable);
8856                 Cvar_RegisterVariable (&gl_fogdensity);
8857                 Cvar_RegisterVariable (&gl_fogred);
8858                 Cvar_RegisterVariable (&gl_foggreen);
8859                 Cvar_RegisterVariable (&gl_fogblue);
8860                 Cvar_RegisterVariable (&gl_fogstart);
8861                 Cvar_RegisterVariable (&gl_fogend);
8862                 Cvar_RegisterVariable (&gl_skyclip);
8863         }
8864         Cvar_RegisterVariable(&r_motionblur);
8865         Cvar_RegisterVariable(&r_motionblur_maxblur);
8866         Cvar_RegisterVariable(&r_motionblur_bmin);
8867         Cvar_RegisterVariable(&r_motionblur_vmin);
8868         Cvar_RegisterVariable(&r_motionblur_vmax);
8869         Cvar_RegisterVariable(&r_motionblur_vcoeff);
8870         Cvar_RegisterVariable(&r_motionblur_randomize);
8871         Cvar_RegisterVariable(&r_damageblur);
8872         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
8873         Cvar_RegisterVariable(&r_equalize_entities_minambient);
8874         Cvar_RegisterVariable(&r_equalize_entities_by);
8875         Cvar_RegisterVariable(&r_equalize_entities_to);
8876         Cvar_RegisterVariable(&r_depthfirst);
8877         Cvar_RegisterVariable(&r_useinfinitefarclip);
8878         Cvar_RegisterVariable(&r_farclip_base);
8879         Cvar_RegisterVariable(&r_farclip_world);
8880         Cvar_RegisterVariable(&r_nearclip);
8881         Cvar_RegisterVariable(&r_showbboxes);
8882         Cvar_RegisterVariable(&r_showsurfaces);
8883         Cvar_RegisterVariable(&r_showtris);
8884         Cvar_RegisterVariable(&r_shownormals);
8885         Cvar_RegisterVariable(&r_showlighting);
8886         Cvar_RegisterVariable(&r_showshadowvolumes);
8887         Cvar_RegisterVariable(&r_showcollisionbrushes);
8888         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
8889         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
8890         Cvar_RegisterVariable(&r_showdisabledepthtest);
8891         Cvar_RegisterVariable(&r_drawportals);
8892         Cvar_RegisterVariable(&r_drawentities);
8893         Cvar_RegisterVariable(&r_draw2d);
8894         Cvar_RegisterVariable(&r_drawworld);
8895         Cvar_RegisterVariable(&r_cullentities_trace);
8896         Cvar_RegisterVariable(&r_cullentities_trace_samples);
8897         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
8898         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
8899         Cvar_RegisterVariable(&r_cullentities_trace_delay);
8900         Cvar_RegisterVariable(&r_drawviewmodel);
8901         Cvar_RegisterVariable(&r_drawexteriormodel);
8902         Cvar_RegisterVariable(&r_speeds);
8903         Cvar_RegisterVariable(&r_fullbrights);
8904         Cvar_RegisterVariable(&r_wateralpha);
8905         Cvar_RegisterVariable(&r_dynamic);
8906         Cvar_RegisterVariable(&r_fakelight);
8907         Cvar_RegisterVariable(&r_fakelight_intensity);
8908         Cvar_RegisterVariable(&r_fullbright);
8909         Cvar_RegisterVariable(&r_shadows);
8910         Cvar_RegisterVariable(&r_shadows_darken);
8911         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
8912         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
8913         Cvar_RegisterVariable(&r_shadows_throwdistance);
8914         Cvar_RegisterVariable(&r_shadows_throwdirection);
8915         Cvar_RegisterVariable(&r_shadows_focus);
8916         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
8917         Cvar_RegisterVariable(&r_q1bsp_skymasking);
8918         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
8919         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
8920         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
8921         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
8922         Cvar_RegisterVariable(&r_fog_exp2);
8923         Cvar_RegisterVariable(&r_drawfog);
8924         Cvar_RegisterVariable(&r_transparentdepthmasking);
8925         Cvar_RegisterVariable(&r_texture_dds_load);
8926         Cvar_RegisterVariable(&r_texture_dds_save);
8927         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
8928         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
8929         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
8930         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
8931         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
8932         Cvar_RegisterVariable(&r_textureunits);
8933         Cvar_RegisterVariable(&gl_combine);
8934         Cvar_RegisterVariable(&r_glsl);
8935         Cvar_RegisterVariable(&r_glsl_deluxemapping);
8936         Cvar_RegisterVariable(&r_glsl_offsetmapping);
8937         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
8938         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
8939         Cvar_RegisterVariable(&r_glsl_postprocess);
8940         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
8941         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
8942         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
8943         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
8944         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
8945         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
8946         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
8947         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
8948
8949         Cvar_RegisterVariable(&r_water);
8950         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
8951         Cvar_RegisterVariable(&r_water_clippingplanebias);
8952         Cvar_RegisterVariable(&r_water_refractdistort);
8953         Cvar_RegisterVariable(&r_water_reflectdistort);
8954         Cvar_RegisterVariable(&r_water_scissormode);
8955         Cvar_RegisterVariable(&r_lerpsprites);
8956         Cvar_RegisterVariable(&r_lerpmodels);
8957         Cvar_RegisterVariable(&r_lerplightstyles);
8958         Cvar_RegisterVariable(&r_waterscroll);
8959         Cvar_RegisterVariable(&r_bloom);
8960         Cvar_RegisterVariable(&r_bloom_colorscale);
8961         Cvar_RegisterVariable(&r_bloom_brighten);
8962         Cvar_RegisterVariable(&r_bloom_blur);
8963         Cvar_RegisterVariable(&r_bloom_resolution);
8964         Cvar_RegisterVariable(&r_bloom_colorexponent);
8965         Cvar_RegisterVariable(&r_bloom_colorsubtract);
8966         Cvar_RegisterVariable(&r_hdr);
8967         Cvar_RegisterVariable(&r_hdr_scenebrightness);
8968         Cvar_RegisterVariable(&r_hdr_glowintensity);
8969         Cvar_RegisterVariable(&r_hdr_range);
8970         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
8971         Cvar_RegisterVariable(&developer_texturelogging);
8972         Cvar_RegisterVariable(&gl_lightmaps);
8973         Cvar_RegisterVariable(&r_test);
8974         Cvar_RegisterVariable(&r_glsl_saturation);
8975         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
8976         Cvar_RegisterVariable(&r_framedatasize);
8977         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
8978                 Cvar_SetValue("r_fullbrights", 0);
8979         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
8980
8981         Cvar_RegisterVariable(&r_track_sprites);
8982         Cvar_RegisterVariable(&r_track_sprites_flags);
8983         Cvar_RegisterVariable(&r_track_sprites_scalew);
8984         Cvar_RegisterVariable(&r_track_sprites_scaleh);
8985         Cvar_RegisterVariable(&r_overheadsprites_perspective);
8986         Cvar_RegisterVariable(&r_overheadsprites_pushback);
8987         Cvar_RegisterVariable(&r_overheadsprites_scalex);
8988         Cvar_RegisterVariable(&r_overheadsprites_scaley);
8989 }
8990
8991 extern void R_Textures_Init(void);
8992 extern void GL_Draw_Init(void);
8993 extern void GL_Main_Init(void);
8994 extern void R_Shadow_Init(void);
8995 extern void R_Sky_Init(void);
8996 extern void GL_Surf_Init(void);
8997 extern void R_Particles_Init(void);
8998 extern void R_Explosion_Init(void);
8999 extern void gl_backend_init(void);
9000 extern void Sbar_Init(void);
9001 extern void R_LightningBeams_Init(void);
9002 extern void Mod_RenderInit(void);
9003 extern void Font_Init(void);
9004
9005 void Render_Init(void)
9006 {
9007         gl_backend_init();
9008         R_Textures_Init();
9009         GL_Main_Init();
9010         Font_Init();
9011         GL_Draw_Init();
9012         R_Shadow_Init();
9013         R_Sky_Init();
9014         GL_Surf_Init();
9015         Sbar_Init();
9016         R_Particles_Init();
9017         R_Explosion_Init();
9018         R_LightningBeams_Init();
9019         Mod_RenderInit();
9020 }
9021
9022 /*
9023 ===============
9024 GL_Init
9025 ===============
9026 */
9027 extern char *ENGINE_EXTENSIONS;
9028 void GL_Init (void)
9029 {
9030         gl_renderer = (const char *)qglGetString(GL_RENDERER);
9031         gl_vendor = (const char *)qglGetString(GL_VENDOR);
9032         gl_version = (const char *)qglGetString(GL_VERSION);
9033         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
9034
9035         if (!gl_extensions)
9036                 gl_extensions = "";
9037         if (!gl_platformextensions)
9038                 gl_platformextensions = "";
9039
9040         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
9041         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
9042         Con_Printf("GL_VERSION: %s\n", gl_version);
9043         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
9044         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
9045
9046         VID_CheckExtensions();
9047
9048         // LordHavoc: report supported extensions
9049         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
9050
9051         // clear to black (loading plaque will be seen over this)
9052         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
9053 }
9054
9055 int R_CullBox(const vec3_t mins, const vec3_t maxs)
9056 {
9057         int i;
9058         mplane_t *p;
9059         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
9060         {
9061                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
9062                 if (i == 4)
9063                         continue;
9064                 p = r_refdef.view.frustum + i;
9065                 switch(p->signbits)
9066                 {
9067                 default:
9068                 case 0:
9069                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
9070                                 return true;
9071                         break;
9072                 case 1:
9073                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
9074                                 return true;
9075                         break;
9076                 case 2:
9077                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
9078                                 return true;
9079                         break;
9080                 case 3:
9081                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
9082                                 return true;
9083                         break;
9084                 case 4:
9085                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
9086                                 return true;
9087                         break;
9088                 case 5:
9089                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
9090                                 return true;
9091                         break;
9092                 case 6:
9093                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
9094                                 return true;
9095                         break;
9096                 case 7:
9097                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
9098                                 return true;
9099                         break;
9100                 }
9101         }
9102         return false;
9103 }
9104
9105 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
9106 {
9107         int i;
9108         const mplane_t *p;
9109         for (i = 0;i < numplanes;i++)
9110         {
9111                 p = planes + i;
9112                 switch(p->signbits)
9113                 {
9114                 default:
9115                 case 0:
9116                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
9117                                 return true;
9118                         break;
9119                 case 1:
9120                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
9121                                 return true;
9122                         break;
9123                 case 2:
9124                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
9125                                 return true;
9126                         break;
9127                 case 3:
9128                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
9129                                 return true;
9130                         break;
9131                 case 4:
9132                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
9133                                 return true;
9134                         break;
9135                 case 5:
9136                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
9137                                 return true;
9138                         break;
9139                 case 6:
9140                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
9141                                 return true;
9142                         break;
9143                 case 7:
9144                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
9145                                 return true;
9146                         break;
9147                 }
9148         }
9149         return false;
9150 }
9151
9152 //==================================================================================
9153
9154 // LordHavoc: this stores temporary data used within the same frame
9155
9156 typedef struct r_framedata_mem_s
9157 {
9158         struct r_framedata_mem_s *purge; // older mem block to free on next frame
9159         size_t size; // how much usable space
9160         size_t current; // how much space in use
9161         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
9162         size_t wantedsize; // how much space was allocated
9163         unsigned char *data; // start of real data (16byte aligned)
9164 }
9165 r_framedata_mem_t;
9166
9167 static r_framedata_mem_t *r_framedata_mem;
9168
9169 void R_FrameData_Reset(void)
9170 {
9171         while (r_framedata_mem)
9172         {
9173                 r_framedata_mem_t *next = r_framedata_mem->purge;
9174                 Mem_Free(r_framedata_mem);
9175                 r_framedata_mem = next;
9176         }
9177 }
9178
9179 void R_FrameData_Resize(void)
9180 {
9181         size_t wantedsize;
9182         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
9183         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
9184         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
9185         {
9186                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
9187                 newmem->wantedsize = wantedsize;
9188                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
9189                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
9190                 newmem->current = 0;
9191                 newmem->mark = 0;
9192                 newmem->purge = r_framedata_mem;
9193                 r_framedata_mem = newmem;
9194         }
9195 }
9196
9197 void R_FrameData_NewFrame(void)
9198 {
9199         R_FrameData_Resize();
9200         if (!r_framedata_mem)
9201                 return;
9202         // if we ran out of space on the last frame, free the old memory now
9203         while (r_framedata_mem->purge)
9204         {
9205                 // repeatedly remove the second item in the list, leaving only head
9206                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
9207                 Mem_Free(r_framedata_mem->purge);
9208                 r_framedata_mem->purge = next;
9209         }
9210         // reset the current mem pointer
9211         r_framedata_mem->current = 0;
9212         r_framedata_mem->mark = 0;
9213 }
9214
9215 void *R_FrameData_Alloc(size_t size)
9216 {
9217         void *data;
9218
9219         // align to 16 byte boundary - the data pointer is already aligned, so we
9220         // only need to ensure the size of every allocation is also aligned
9221         size = (size + 15) & ~15;
9222
9223         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
9224         {
9225                 // emergency - we ran out of space, allocate more memory
9226                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
9227                 R_FrameData_Resize();
9228         }
9229
9230         data = r_framedata_mem->data + r_framedata_mem->current;
9231         r_framedata_mem->current += size;
9232
9233         // count the usage for stats
9234         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
9235         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
9236
9237         return (void *)data;
9238 }
9239
9240 void *R_FrameData_Store(size_t size, void *data)
9241 {
9242         void *d = R_FrameData_Alloc(size);
9243         if (d && data)
9244                 memcpy(d, data, size);
9245         return d;
9246 }
9247
9248 void R_FrameData_SetMark(void)
9249 {
9250         if (!r_framedata_mem)
9251                 return;
9252         r_framedata_mem->mark = r_framedata_mem->current;
9253 }
9254
9255 void R_FrameData_ReturnToMark(void)
9256 {
9257         if (!r_framedata_mem)
9258                 return;
9259         r_framedata_mem->current = r_framedata_mem->mark;
9260 }
9261
9262 //==================================================================================
9263
9264 // LordHavoc: animcache originally written by Echon, rewritten since then
9265
9266 /**
9267  * Animation cache prevents re-generating mesh data for an animated model
9268  * multiple times in one frame for lighting, shadowing, reflections, etc.
9269  */
9270
9271 void R_AnimCache_Free(void)
9272 {
9273 }
9274
9275 void R_AnimCache_ClearCache(void)
9276 {
9277         int i;
9278         entity_render_t *ent;
9279
9280         for (i = 0;i < r_refdef.scene.numentities;i++)
9281         {
9282                 ent = r_refdef.scene.entities[i];
9283                 ent->animcache_vertex3f = NULL;
9284                 ent->animcache_normal3f = NULL;
9285                 ent->animcache_svector3f = NULL;
9286                 ent->animcache_tvector3f = NULL;
9287                 ent->animcache_vertexmesh = NULL;
9288                 ent->animcache_vertex3fbuffer = NULL;
9289                 ent->animcache_vertexmeshbuffer = NULL;
9290         }
9291 }
9292
9293 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
9294 {
9295         int i;
9296
9297         // check if we need the meshbuffers
9298         if (!vid.useinterleavedarrays)
9299                 return;
9300
9301         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
9302                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
9303         // TODO: upload vertex3f buffer?
9304         if (ent->animcache_vertexmesh)
9305         {
9306                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
9307                 for (i = 0;i < numvertices;i++)
9308                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
9309                 if (ent->animcache_svector3f)
9310                         for (i = 0;i < numvertices;i++)
9311                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
9312                 if (ent->animcache_tvector3f)
9313                         for (i = 0;i < numvertices;i++)
9314                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
9315                 if (ent->animcache_normal3f)
9316                         for (i = 0;i < numvertices;i++)
9317                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
9318                 // TODO: upload vertexmeshbuffer?
9319         }
9320 }
9321
9322 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
9323 {
9324         dp_model_t *model = ent->model;
9325         int numvertices;
9326         // see if it's already cached this frame
9327         if (ent->animcache_vertex3f)
9328         {
9329                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
9330                 if (wantnormals || wanttangents)
9331                 {
9332                         if (ent->animcache_normal3f)
9333                                 wantnormals = false;
9334                         if (ent->animcache_svector3f)
9335                                 wanttangents = false;
9336                         if (wantnormals || wanttangents)
9337                         {
9338                                 numvertices = model->surfmesh.num_vertices;
9339                                 if (wantnormals)
9340                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
9341                                 if (wanttangents)
9342                                 {
9343                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
9344                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
9345                                 }
9346                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
9347                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
9348                         }
9349                 }
9350         }
9351         else
9352         {
9353                 // see if this ent is worth caching
9354                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
9355                         return false;
9356                 // get some memory for this entity and generate mesh data
9357                 numvertices = model->surfmesh.num_vertices;
9358                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
9359                 if (wantnormals)
9360                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
9361                 if (wanttangents)
9362                 {
9363                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
9364                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
9365                 }
9366                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
9367                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
9368         }
9369         return true;
9370 }
9371
9372 void R_AnimCache_CacheVisibleEntities(void)
9373 {
9374         int i;
9375         qboolean wantnormals = true;
9376         qboolean wanttangents = !r_showsurfaces.integer;
9377
9378         switch(vid.renderpath)
9379         {
9380         case RENDERPATH_GL20:
9381         case RENDERPATH_CGGL:
9382         case RENDERPATH_D3D9:
9383         case RENDERPATH_D3D10:
9384         case RENDERPATH_D3D11:
9385         case RENDERPATH_GLES2:
9386                 break;
9387         case RENDERPATH_GL13:
9388         case RENDERPATH_GL11:
9389                 wanttangents = false;
9390                 break;
9391         case RENDERPATH_SOFT:
9392                 break;
9393         }
9394
9395         if (r_shownormals.integer)
9396                 wanttangents = wantnormals = true;
9397
9398         // TODO: thread this
9399         // NOTE: R_PrepareRTLights() also caches entities
9400
9401         for (i = 0;i < r_refdef.scene.numentities;i++)
9402                 if (r_refdef.viewcache.entityvisible[i])
9403                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
9404 }
9405
9406 //==================================================================================
9407
9408 static void R_View_UpdateEntityLighting (void)
9409 {
9410         int i;
9411         entity_render_t *ent;
9412         vec3_t tempdiffusenormal, avg;
9413         vec_t f, fa, fd, fdd;
9414         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
9415
9416         for (i = 0;i < r_refdef.scene.numentities;i++)
9417         {
9418                 ent = r_refdef.scene.entities[i];
9419
9420                 // skip unseen models
9421                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
9422                         continue;
9423
9424                 // skip bsp models
9425                 if (ent->model && ent->model->brush.num_leafs)
9426                 {
9427                         // TODO: use modellight for r_ambient settings on world?
9428                         VectorSet(ent->modellight_ambient, 0, 0, 0);
9429                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
9430                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
9431                         continue;
9432                 }
9433
9434                 // fetch the lighting from the worldmodel data
9435                 VectorClear(ent->modellight_ambient);
9436                 VectorClear(ent->modellight_diffuse);
9437                 VectorClear(tempdiffusenormal);
9438                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
9439                 {
9440                         vec3_t org;
9441                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9442
9443                         // complete lightning for lit sprites
9444                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
9445                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
9446                         {
9447                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
9448                                         org[2] = org[2] + r_overheadsprites_pushback.value;
9449                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
9450                         }
9451                         else
9452                                 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
9453
9454                         if(ent->flags & RENDER_EQUALIZE)
9455                         {
9456                                 // first fix up ambient lighting...
9457                                 if(r_equalize_entities_minambient.value > 0)
9458                                 {
9459                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
9460                                         if(fd > 0)
9461                                         {
9462                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
9463                                                 if(fa < r_equalize_entities_minambient.value * fd)
9464                                                 {
9465                                                         // solve:
9466                                                         //   fa'/fd' = minambient
9467                                                         //   fa'+0.25*fd' = fa+0.25*fd
9468                                                         //   ...
9469                                                         //   fa' = fd' * minambient
9470                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
9471                                                         //   ...
9472                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
9473                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
9474                                                         //   ...
9475                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
9476                                                         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
9477                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
9478                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
9479                                                 }
9480                                         }
9481                                 }
9482
9483                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
9484                                 {
9485                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
9486                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
9487                                         f = fa + 0.25 * fd;
9488                                         if(f > 0)
9489                                         {
9490                                                 // adjust brightness and saturation to target
9491                                                 avg[0] = avg[1] = avg[2] = fa / f;
9492                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
9493                                                 avg[0] = avg[1] = avg[2] = fd / f;
9494                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
9495                                         }
9496                                 }
9497                         }
9498                 }
9499                 else // highly rare
9500                         VectorSet(ent->modellight_ambient, 1, 1, 1);
9501
9502                 // move the light direction into modelspace coordinates for lighting code
9503                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
9504                 if(VectorLength2(ent->modellight_lightdir) == 0)
9505                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
9506                 VectorNormalize(ent->modellight_lightdir);
9507         }
9508 }
9509
9510 #define MAX_LINEOFSIGHTTRACES 64
9511
9512 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
9513 {
9514         int i;
9515         vec3_t boxmins, boxmaxs;
9516         vec3_t start;
9517         vec3_t end;
9518         dp_model_t *model = r_refdef.scene.worldmodel;
9519
9520         if (!model || !model->brush.TraceLineOfSight)
9521                 return true;
9522
9523         // expand the box a little
9524         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
9525         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
9526         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
9527         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
9528         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
9529         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
9530
9531         // return true if eye is inside enlarged box
9532         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
9533                 return true;
9534
9535         // try center
9536         VectorCopy(eye, start);
9537         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
9538         if (model->brush.TraceLineOfSight(model, start, end))
9539                 return true;
9540
9541         // try various random positions
9542         for (i = 0;i < numsamples;i++)
9543         {
9544                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
9545                 if (model->brush.TraceLineOfSight(model, start, end))
9546                         return true;
9547         }
9548
9549         return false;
9550 }
9551
9552
9553 static void R_View_UpdateEntityVisible (void)
9554 {
9555         int i;
9556         int renderimask;
9557         int samples;
9558         entity_render_t *ent;
9559
9560         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
9561                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
9562                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
9563                 :                                                          RENDER_EXTERIORMODEL;
9564         if (!r_drawviewmodel.integer)
9565                 renderimask |= RENDER_VIEWMODEL;
9566         if (!r_drawexteriormodel.integer)
9567                 renderimask |= RENDER_EXTERIORMODEL;
9568         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
9569         {
9570                 // worldmodel can check visibility
9571                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
9572                 for (i = 0;i < r_refdef.scene.numentities;i++)
9573                 {
9574                         ent = r_refdef.scene.entities[i];
9575                         if (!(ent->flags & renderimask))
9576                         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)))
9577                         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))
9578                                 r_refdef.viewcache.entityvisible[i] = true;
9579                 }
9580                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
9581                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
9582                 {
9583                         for (i = 0;i < r_refdef.scene.numentities;i++)
9584                         {
9585                                 ent = r_refdef.scene.entities[i];
9586                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
9587                                 {
9588                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
9589                                         if (samples < 0)
9590                                                 continue; // temp entities do pvs only
9591                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
9592                                                 ent->last_trace_visibility = realtime;
9593                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
9594                                                 r_refdef.viewcache.entityvisible[i] = 0;
9595                                 }
9596                         }
9597                 }
9598         }
9599         else
9600         {
9601                 // no worldmodel or it can't check visibility
9602                 for (i = 0;i < r_refdef.scene.numentities;i++)
9603                 {
9604                         ent = r_refdef.scene.entities[i];
9605                         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));
9606                 }
9607         }
9608 }
9609
9610 /// only used if skyrendermasked, and normally returns false
9611 int R_DrawBrushModelsSky (void)
9612 {
9613         int i, sky;
9614         entity_render_t *ent;
9615
9616         sky = false;
9617         for (i = 0;i < r_refdef.scene.numentities;i++)
9618         {
9619                 if (!r_refdef.viewcache.entityvisible[i])
9620                         continue;
9621                 ent = r_refdef.scene.entities[i];
9622                 if (!ent->model || !ent->model->DrawSky)
9623                         continue;
9624                 ent->model->DrawSky(ent);
9625                 sky = true;
9626         }
9627         return sky;
9628 }
9629
9630 static void R_DrawNoModel(entity_render_t *ent);
9631 static void R_DrawModels(void)
9632 {
9633         int i;
9634         entity_render_t *ent;
9635
9636         for (i = 0;i < r_refdef.scene.numentities;i++)
9637         {
9638                 if (!r_refdef.viewcache.entityvisible[i])
9639                         continue;
9640                 ent = r_refdef.scene.entities[i];
9641                 r_refdef.stats.entities++;
9642                 if (ent->model && ent->model->Draw != NULL)
9643                         ent->model->Draw(ent);
9644                 else
9645                         R_DrawNoModel(ent);
9646         }
9647 }
9648
9649 static void R_DrawModelsDepth(void)
9650 {
9651         int i;
9652         entity_render_t *ent;
9653
9654         for (i = 0;i < r_refdef.scene.numentities;i++)
9655         {
9656                 if (!r_refdef.viewcache.entityvisible[i])
9657                         continue;
9658                 ent = r_refdef.scene.entities[i];
9659                 if (ent->model && ent->model->DrawDepth != NULL)
9660                         ent->model->DrawDepth(ent);
9661         }
9662 }
9663
9664 static void R_DrawModelsDebug(void)
9665 {
9666         int i;
9667         entity_render_t *ent;
9668
9669         for (i = 0;i < r_refdef.scene.numentities;i++)
9670         {
9671                 if (!r_refdef.viewcache.entityvisible[i])
9672                         continue;
9673                 ent = r_refdef.scene.entities[i];
9674                 if (ent->model && ent->model->DrawDebug != NULL)
9675                         ent->model->DrawDebug(ent);
9676         }
9677 }
9678
9679 static void R_DrawModelsAddWaterPlanes(void)
9680 {
9681         int i;
9682         entity_render_t *ent;
9683
9684         for (i = 0;i < r_refdef.scene.numentities;i++)
9685         {
9686                 if (!r_refdef.viewcache.entityvisible[i])
9687                         continue;
9688                 ent = r_refdef.scene.entities[i];
9689                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
9690                         ent->model->DrawAddWaterPlanes(ent);
9691         }
9692 }
9693
9694 static void R_View_SetFrustum(const int *scissor)
9695 {
9696         int i;
9697         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
9698         vec3_t forward, left, up, origin, v;
9699
9700         if(scissor)
9701         {
9702                 // flipped x coordinates (because x points left here)
9703                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
9704                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
9705
9706                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
9707                 switch(vid.renderpath)
9708                 {
9709                         case RENDERPATH_D3D9:
9710                         case RENDERPATH_D3D10:
9711                         case RENDERPATH_D3D11:
9712                         case RENDERPATH_SOFT:
9713                                 // non-flipped y coordinates
9714                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
9715                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
9716                                 break;
9717                         case RENDERPATH_GL11:
9718                         case RENDERPATH_GL13:
9719                         case RENDERPATH_GL20:
9720                         case RENDERPATH_CGGL:
9721                         case RENDERPATH_GLES2:
9722                                 // non-flipped y coordinates
9723                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
9724                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
9725                                 break;
9726                 }
9727         }
9728
9729         // we can't trust r_refdef.view.forward and friends in reflected scenes
9730         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
9731
9732 #if 0
9733         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
9734         r_refdef.view.frustum[0].normal[1] = 0 - 0;
9735         r_refdef.view.frustum[0].normal[2] = -1 - 0;
9736         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
9737         r_refdef.view.frustum[1].normal[1] = 0 + 0;
9738         r_refdef.view.frustum[1].normal[2] = -1 + 0;
9739         r_refdef.view.frustum[2].normal[0] = 0 - 0;
9740         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
9741         r_refdef.view.frustum[2].normal[2] = -1 - 0;
9742         r_refdef.view.frustum[3].normal[0] = 0 + 0;
9743         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
9744         r_refdef.view.frustum[3].normal[2] = -1 + 0;
9745 #endif
9746
9747 #if 0
9748         zNear = r_refdef.nearclip;
9749         nudge = 1.0 - 1.0 / (1<<23);
9750         r_refdef.view.frustum[4].normal[0] = 0 - 0;
9751         r_refdef.view.frustum[4].normal[1] = 0 - 0;
9752         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
9753         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
9754         r_refdef.view.frustum[5].normal[0] = 0 + 0;
9755         r_refdef.view.frustum[5].normal[1] = 0 + 0;
9756         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
9757         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
9758 #endif
9759
9760
9761
9762 #if 0
9763         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
9764         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
9765         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
9766         r_refdef.view.frustum[0].dist = m[15] - m[12];
9767
9768         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
9769         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
9770         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
9771         r_refdef.view.frustum[1].dist = m[15] + m[12];
9772
9773         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
9774         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
9775         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
9776         r_refdef.view.frustum[2].dist = m[15] - m[13];
9777
9778         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
9779         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
9780         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
9781         r_refdef.view.frustum[3].dist = m[15] + m[13];
9782
9783         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
9784         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
9785         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
9786         r_refdef.view.frustum[4].dist = m[15] - m[14];
9787
9788         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
9789         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
9790         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
9791         r_refdef.view.frustum[5].dist = m[15] + m[14];
9792 #endif
9793
9794         if (r_refdef.view.useperspective)
9795         {
9796                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
9797                 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]);
9798                 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]);
9799                 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]);
9800                 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]);
9801
9802                 // then the normals from the corners relative to origin
9803                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
9804                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
9805                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
9806                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
9807
9808                 // in a NORMAL view, forward cross left == up
9809                 // in a REFLECTED view, forward cross left == down
9810                 // so our cross products above need to be adjusted for a left handed coordinate system
9811                 CrossProduct(forward, left, v);
9812                 if(DotProduct(v, up) < 0)
9813                 {
9814                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
9815                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
9816                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
9817                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
9818                 }
9819
9820                 // Leaving those out was a mistake, those were in the old code, and they
9821                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
9822                 // I couldn't reproduce it after adding those normalizations. --blub
9823                 VectorNormalize(r_refdef.view.frustum[0].normal);
9824                 VectorNormalize(r_refdef.view.frustum[1].normal);
9825                 VectorNormalize(r_refdef.view.frustum[2].normal);
9826                 VectorNormalize(r_refdef.view.frustum[3].normal);
9827
9828                 // make the corners absolute
9829                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
9830                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
9831                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
9832                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
9833
9834                 // one more normal
9835                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
9836
9837                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
9838                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
9839                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
9840                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
9841                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
9842         }
9843         else
9844         {
9845                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
9846                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
9847                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
9848                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
9849                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
9850                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
9851                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
9852                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
9853                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
9854                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
9855         }
9856         r_refdef.view.numfrustumplanes = 5;
9857
9858         if (r_refdef.view.useclipplane)
9859         {
9860                 r_refdef.view.numfrustumplanes = 6;
9861                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
9862         }
9863
9864         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
9865                 PlaneClassify(r_refdef.view.frustum + i);
9866
9867         // LordHavoc: note to all quake engine coders, Quake had a special case
9868         // for 90 degrees which assumed a square view (wrong), so I removed it,
9869         // Quake2 has it disabled as well.
9870
9871         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
9872         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
9873         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
9874         //PlaneClassify(&frustum[0]);
9875
9876         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
9877         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
9878         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
9879         //PlaneClassify(&frustum[1]);
9880
9881         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
9882         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
9883         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
9884         //PlaneClassify(&frustum[2]);
9885
9886         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
9887         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
9888         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
9889         //PlaneClassify(&frustum[3]);
9890
9891         // nearclip plane
9892         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
9893         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
9894         //PlaneClassify(&frustum[4]);
9895 }
9896
9897 void R_View_UpdateWithScissor(const int *myscissor)
9898 {
9899         R_Main_ResizeViewCache();
9900         R_View_SetFrustum(myscissor);
9901         R_View_WorldVisibility(r_refdef.view.useclipplane);
9902         R_View_UpdateEntityVisible();
9903         R_View_UpdateEntityLighting();
9904 }
9905
9906 void R_View_Update(void)
9907 {
9908         R_Main_ResizeViewCache();
9909         R_View_SetFrustum(NULL);
9910         R_View_WorldVisibility(r_refdef.view.useclipplane);
9911         R_View_UpdateEntityVisible();
9912         R_View_UpdateEntityLighting();
9913 }
9914
9915 void R_SetupView(qboolean allowwaterclippingplane)
9916 {
9917         const float *customclipplane = NULL;
9918         float plane[4];
9919         if (r_refdef.view.useclipplane && allowwaterclippingplane)
9920         {
9921                 // LordHavoc: couldn't figure out how to make this approach the
9922                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
9923                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
9924                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
9925                         dist = r_refdef.view.clipplane.dist;
9926                 plane[0] = r_refdef.view.clipplane.normal[0];
9927                 plane[1] = r_refdef.view.clipplane.normal[1];
9928                 plane[2] = r_refdef.view.clipplane.normal[2];
9929                 plane[3] = dist;
9930                 customclipplane = plane;
9931         }
9932
9933         if (!r_refdef.view.useperspective)
9934                 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);
9935         else if (vid.stencil && r_useinfinitefarclip.integer)
9936                 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);
9937         else
9938                 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);
9939         R_SetViewport(&r_refdef.view.viewport);
9940 }
9941
9942 void R_EntityMatrix(const matrix4x4_t *matrix)
9943 {
9944         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
9945         {
9946                 gl_modelmatrixchanged = false;
9947                 gl_modelmatrix = *matrix;
9948                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
9949                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
9950                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
9951                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
9952                 CHECKGLERROR
9953                 switch(vid.renderpath)
9954                 {
9955                 case RENDERPATH_D3D9:
9956 #ifdef SUPPORTD3D
9957                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
9958                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
9959 #endif
9960                         break;
9961                 case RENDERPATH_D3D10:
9962                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
9963                         break;
9964                 case RENDERPATH_D3D11:
9965                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
9966                         break;
9967                 case RENDERPATH_GL20:
9968                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
9969                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
9970                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
9971                         break;
9972                 case RENDERPATH_CGGL:
9973 #ifdef SUPPORTCG
9974                         CHECKCGERROR
9975                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
9976                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
9977                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
9978 #endif
9979                         break;
9980                 case RENDERPATH_GL13:
9981                 case RENDERPATH_GL11:
9982                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
9983                         break;
9984                 case RENDERPATH_SOFT:
9985                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
9986                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
9987                         break;
9988                 case RENDERPATH_GLES2:
9989                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
9990                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
9991                         break;
9992                 }
9993         }
9994 }
9995
9996 void R_ResetViewRendering2D(void)
9997 {
9998         r_viewport_t viewport;
9999         DrawQ_Finish();
10000
10001         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
10002         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);
10003         R_SetViewport(&viewport);
10004         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
10005         GL_Color(1, 1, 1, 1);
10006         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10007         GL_BlendFunc(GL_ONE, GL_ZERO);
10008         GL_AlphaTest(false);
10009         GL_ScissorTest(false);
10010         GL_DepthMask(false);
10011         GL_DepthRange(0, 1);
10012         GL_DepthTest(false);
10013         GL_DepthFunc(GL_LEQUAL);
10014         R_EntityMatrix(&identitymatrix);
10015         R_Mesh_ResetTextureState();
10016         GL_PolygonOffset(0, 0);
10017         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
10018         switch(vid.renderpath)
10019         {
10020         case RENDERPATH_GL11:
10021         case RENDERPATH_GL13:
10022         case RENDERPATH_GL20:
10023         case RENDERPATH_CGGL:
10024         case RENDERPATH_GLES2:
10025                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
10026                 break;
10027         case RENDERPATH_D3D9:
10028         case RENDERPATH_D3D10:
10029         case RENDERPATH_D3D11:
10030         case RENDERPATH_SOFT:
10031                 break;
10032         }
10033         GL_CullFace(GL_NONE);
10034 }
10035
10036 void R_ResetViewRendering3D(void)
10037 {
10038         DrawQ_Finish();
10039
10040         R_SetupView(true);
10041         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
10042         GL_Color(1, 1, 1, 1);
10043         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10044         GL_BlendFunc(GL_ONE, GL_ZERO);
10045         GL_AlphaTest(false);
10046         GL_ScissorTest(true);
10047         GL_DepthMask(true);
10048         GL_DepthRange(0, 1);
10049         GL_DepthTest(true);
10050         GL_DepthFunc(GL_LEQUAL);
10051         R_EntityMatrix(&identitymatrix);
10052         R_Mesh_ResetTextureState();
10053         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10054         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
10055         switch(vid.renderpath)
10056         {
10057         case RENDERPATH_GL11:
10058         case RENDERPATH_GL13:
10059         case RENDERPATH_GL20:
10060         case RENDERPATH_CGGL:
10061         case RENDERPATH_GLES2:
10062                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
10063                 break;
10064         case RENDERPATH_D3D9:
10065         case RENDERPATH_D3D10:
10066         case RENDERPATH_D3D11:
10067         case RENDERPATH_SOFT:
10068                 break;
10069         }
10070         GL_CullFace(r_refdef.view.cullface_back);
10071 }
10072
10073 /*
10074 ================
10075 R_RenderView_UpdateViewVectors
10076 ================
10077 */
10078 static void R_RenderView_UpdateViewVectors(void)
10079 {
10080         // break apart the view matrix into vectors for various purposes
10081         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
10082         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
10083         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
10084         VectorNegate(r_refdef.view.left, r_refdef.view.right);
10085         // make an inverted copy of the view matrix for tracking sprites
10086         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
10087 }
10088
10089 void R_RenderScene(void);
10090 void R_RenderWaterPlanes(void);
10091
10092 static void R_Water_StartFrame(void)
10093 {
10094         int i;
10095         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
10096         r_waterstate_waterplane_t *p;
10097
10098         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
10099                 return;
10100
10101         switch(vid.renderpath)
10102         {
10103         case RENDERPATH_GL20:
10104         case RENDERPATH_CGGL:
10105         case RENDERPATH_D3D9:
10106         case RENDERPATH_D3D10:
10107         case RENDERPATH_D3D11:
10108         case RENDERPATH_SOFT:
10109                 break;
10110         case RENDERPATH_GL13:
10111         case RENDERPATH_GL11:
10112         case RENDERPATH_GLES2:
10113                 return;
10114         }
10115
10116         // set waterwidth and waterheight to the water resolution that will be
10117         // used (often less than the screen resolution for faster rendering)
10118         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
10119         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
10120
10121         // calculate desired texture sizes
10122         // can't use water if the card does not support the texture size
10123         if (!r_water.integer || r_showsurfaces.integer)
10124                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
10125         else if (vid.support.arb_texture_non_power_of_two)
10126         {
10127                 texturewidth = waterwidth;
10128                 textureheight = waterheight;
10129                 camerawidth = waterwidth;
10130                 cameraheight = waterheight;
10131         }
10132         else
10133         {
10134                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
10135                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
10136                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
10137                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
10138         }
10139
10140         // allocate textures as needed
10141         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
10142         {
10143                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
10144                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
10145                 {
10146                         if (p->texture_refraction)
10147                                 R_FreeTexture(p->texture_refraction);
10148                         p->texture_refraction = NULL;
10149                         if (p->texture_reflection)
10150                                 R_FreeTexture(p->texture_reflection);
10151                         p->texture_reflection = NULL;
10152                         if (p->texture_camera)
10153                                 R_FreeTexture(p->texture_camera);
10154                         p->texture_camera = NULL;
10155                 }
10156                 memset(&r_waterstate, 0, sizeof(r_waterstate));
10157                 r_waterstate.texturewidth = texturewidth;
10158                 r_waterstate.textureheight = textureheight;
10159                 r_waterstate.camerawidth = camerawidth;
10160                 r_waterstate.cameraheight = cameraheight;
10161         }
10162
10163         if (r_waterstate.texturewidth)
10164         {
10165                 r_waterstate.enabled = true;
10166
10167                 // when doing a reduced render (HDR) we want to use a smaller area
10168                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
10169                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
10170
10171                 // set up variables that will be used in shader setup
10172                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
10173                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
10174                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
10175                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
10176         }
10177
10178         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
10179         r_waterstate.numwaterplanes = 0;
10180 }
10181
10182 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
10183 {
10184         int triangleindex, planeindex;
10185         const int *e;
10186         vec3_t vert[3];
10187         vec3_t normal;
10188         vec3_t center;
10189         mplane_t plane;
10190         r_waterstate_waterplane_t *p;
10191         texture_t *t = R_GetCurrentTexture(surface->texture);
10192
10193         // just use the first triangle with a valid normal for any decisions
10194         VectorClear(normal);
10195         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
10196         {
10197                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
10198                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
10199                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
10200                 TriangleNormal(vert[0], vert[1], vert[2], normal);
10201                 if (VectorLength2(normal) >= 0.001)
10202                         break;
10203         }
10204
10205         VectorCopy(normal, plane.normal);
10206         VectorNormalize(plane.normal);
10207         plane.dist = DotProduct(vert[0], plane.normal);
10208         PlaneClassify(&plane);
10209         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
10210         {
10211                 // skip backfaces (except if nocullface is set)
10212                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
10213                         return;
10214                 VectorNegate(plane.normal, plane.normal);
10215                 plane.dist *= -1;
10216                 PlaneClassify(&plane);
10217         }
10218
10219
10220         // find a matching plane if there is one
10221         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10222                 if(p->camera_entity == t->camera_entity)
10223                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
10224                                 break;
10225         if (planeindex >= r_waterstate.maxwaterplanes)
10226                 return; // nothing we can do, out of planes
10227
10228         // if this triangle does not fit any known plane rendered this frame, add one
10229         if (planeindex >= r_waterstate.numwaterplanes)
10230         {
10231                 // store the new plane
10232                 r_waterstate.numwaterplanes++;
10233                 p->plane = plane;
10234                 // clear materialflags and pvs
10235                 p->materialflags = 0;
10236                 p->pvsvalid = false;
10237                 p->camera_entity = t->camera_entity;
10238                 VectorCopy(surface->mins, p->mins);
10239                 VectorCopy(surface->maxs, p->maxs);
10240         }
10241         else
10242         {
10243                 // merge mins/maxs
10244                 p->mins[0] = min(p->mins[0], surface->mins[0]);
10245                 p->mins[1] = min(p->mins[1], surface->mins[1]);
10246                 p->mins[2] = min(p->mins[2], surface->mins[2]);
10247                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
10248                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
10249                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
10250         }
10251         // merge this surface's materialflags into the waterplane
10252         p->materialflags |= t->currentmaterialflags;
10253         if(!(p->materialflags & MATERIALFLAG_CAMERA))
10254         {
10255                 // merge this surface's PVS into the waterplane
10256                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
10257                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
10258                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
10259                 {
10260                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
10261                         p->pvsvalid = true;
10262                 }
10263         }
10264 }
10265
10266 static void R_Water_ProcessPlanes(void)
10267 {
10268         int myscissor[4];
10269         r_refdef_view_t originalview;
10270         r_refdef_view_t myview;
10271         int planeindex;
10272         r_waterstate_waterplane_t *p;
10273         vec3_t visorigin;
10274
10275         originalview = r_refdef.view;
10276
10277         // make sure enough textures are allocated
10278         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10279         {
10280                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10281                 {
10282                         if (!p->texture_refraction)
10283                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
10284                         if (!p->texture_refraction)
10285                                 goto error;
10286                 }
10287                 else if (p->materialflags & MATERIALFLAG_CAMERA)
10288                 {
10289                         if (!p->texture_camera)
10290                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
10291                         if (!p->texture_camera)
10292                                 goto error;
10293                 }
10294
10295                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
10296                 {
10297                         if (!p->texture_reflection)
10298                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
10299                         if (!p->texture_reflection)
10300                                 goto error;
10301                 }
10302         }
10303
10304         // render views
10305         r_refdef.view = originalview;
10306         r_refdef.view.showdebug = false;
10307         r_refdef.view.width = r_waterstate.waterwidth;
10308         r_refdef.view.height = r_waterstate.waterheight;
10309         r_refdef.view.useclipplane = true;
10310         myview = r_refdef.view;
10311         r_waterstate.renderingscene = true;
10312         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10313         {
10314                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
10315                 {
10316                         r_refdef.view = myview;
10317                         if(r_water_scissormode.integer)
10318                         {
10319                                 R_SetupView(true);
10320                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
10321                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
10322                         }
10323
10324                         // render reflected scene and copy into texture
10325                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
10326                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
10327                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
10328                         r_refdef.view.clipplane = p->plane;
10329
10330                         // reverse the cullface settings for this render
10331                         r_refdef.view.cullface_front = GL_FRONT;
10332                         r_refdef.view.cullface_back = GL_BACK;
10333                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
10334                         {
10335                                 r_refdef.view.usecustompvs = true;
10336                                 if (p->pvsvalid)
10337                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
10338                                 else
10339                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
10340                         }
10341
10342                         R_ResetViewRendering3D();
10343                         R_ClearScreen(r_refdef.fogenabled);
10344                         if(r_water_scissormode.integer & 2)
10345                                 R_View_UpdateWithScissor(myscissor);
10346                         else
10347                                 R_View_Update();
10348                         if(r_water_scissormode.integer & 1)
10349                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
10350                         R_RenderScene();
10351
10352                         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);
10353                 }
10354
10355                 // render the normal view scene and copy into texture
10356                 // (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)
10357                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10358                 {
10359                         r_refdef.view = myview;
10360                         if(r_water_scissormode.integer)
10361                         {
10362                                 R_SetupView(true);
10363                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
10364                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
10365                         }
10366
10367                         r_waterstate.renderingrefraction = true;
10368
10369                         r_refdef.view.clipplane = p->plane;
10370                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
10371                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
10372
10373                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
10374                         {
10375                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
10376                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
10377                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
10378                                 R_RenderView_UpdateViewVectors();
10379                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
10380                                 {
10381                                         r_refdef.view.usecustompvs = true;
10382                                         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);
10383                                 }
10384                         }
10385
10386                         PlaneClassify(&r_refdef.view.clipplane);
10387
10388                         R_ResetViewRendering3D();
10389                         R_ClearScreen(r_refdef.fogenabled);
10390                         if(r_water_scissormode.integer & 2)
10391                                 R_View_UpdateWithScissor(myscissor);
10392                         else
10393                                 R_View_Update();
10394                         if(r_water_scissormode.integer & 1)
10395                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
10396                         R_RenderScene();
10397
10398                         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);
10399                         r_waterstate.renderingrefraction = false;
10400                 }
10401                 else if (p->materialflags & MATERIALFLAG_CAMERA)
10402                 {
10403                         r_refdef.view = myview;
10404
10405                         r_refdef.view.clipplane = p->plane;
10406                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
10407                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
10408
10409                         r_refdef.view.width = r_waterstate.camerawidth;
10410                         r_refdef.view.height = r_waterstate.cameraheight;
10411                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
10412                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
10413
10414                         if(p->camera_entity)
10415                         {
10416                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
10417                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
10418                         }
10419
10420                         // note: all of the view is used for displaying... so
10421                         // there is no use in scissoring
10422
10423                         // reverse the cullface settings for this render
10424                         r_refdef.view.cullface_front = GL_FRONT;
10425                         r_refdef.view.cullface_back = GL_BACK;
10426                         // also reverse the view matrix
10427                         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
10428                         R_RenderView_UpdateViewVectors();
10429                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
10430                         {
10431                                 r_refdef.view.usecustompvs = true;
10432                                 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);
10433                         }
10434                         
10435                         // camera needs no clipplane
10436                         r_refdef.view.useclipplane = false;
10437
10438                         PlaneClassify(&r_refdef.view.clipplane);
10439
10440                         R_ResetViewRendering3D();
10441                         R_ClearScreen(r_refdef.fogenabled);
10442                         R_View_Update();
10443                         R_RenderScene();
10444
10445                         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);
10446                         r_waterstate.renderingrefraction = false;
10447                 }
10448
10449         }
10450         r_waterstate.renderingscene = false;
10451         r_refdef.view = originalview;
10452         R_ResetViewRendering3D();
10453         R_ClearScreen(r_refdef.fogenabled);
10454         R_View_Update();
10455         return;
10456 error:
10457         r_refdef.view = originalview;
10458         r_waterstate.renderingscene = false;
10459         Cvar_SetValueQuick(&r_water, 0);
10460         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
10461         return;
10462 }
10463
10464 void R_Bloom_StartFrame(void)
10465 {
10466         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
10467
10468         switch(vid.renderpath)
10469         {
10470         case RENDERPATH_GL20:
10471         case RENDERPATH_CGGL:
10472         case RENDERPATH_D3D9:
10473         case RENDERPATH_D3D10:
10474         case RENDERPATH_D3D11:
10475         case RENDERPATH_SOFT:
10476                 break;
10477         case RENDERPATH_GL13:
10478         case RENDERPATH_GL11:
10479         case RENDERPATH_GLES2:
10480                 return;
10481         }
10482
10483         // set bloomwidth and bloomheight to the bloom resolution that will be
10484         // used (often less than the screen resolution for faster rendering)
10485         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
10486         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
10487         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
10488         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
10489         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
10490
10491         // calculate desired texture sizes
10492         if (vid.support.arb_texture_non_power_of_two)
10493         {
10494                 screentexturewidth = r_refdef.view.width;
10495                 screentextureheight = r_refdef.view.height;
10496                 bloomtexturewidth = r_bloomstate.bloomwidth;
10497                 bloomtextureheight = r_bloomstate.bloomheight;
10498         }
10499         else
10500         {
10501                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
10502                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
10503                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
10504                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
10505         }
10506
10507         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))
10508         {
10509                 Cvar_SetValueQuick(&r_hdr, 0);
10510                 Cvar_SetValueQuick(&r_bloom, 0);
10511                 Cvar_SetValueQuick(&r_motionblur, 0);
10512                 Cvar_SetValueQuick(&r_damageblur, 0);
10513         }
10514
10515         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)))
10516                 screentexturewidth = screentextureheight = 0;
10517         if (!r_hdr.integer && !r_bloom.integer)
10518                 bloomtexturewidth = bloomtextureheight = 0;
10519
10520         // allocate textures as needed
10521         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
10522         {
10523                 if (r_bloomstate.texture_screen)
10524                         R_FreeTexture(r_bloomstate.texture_screen);
10525                 r_bloomstate.texture_screen = NULL;
10526                 r_bloomstate.screentexturewidth = screentexturewidth;
10527                 r_bloomstate.screentextureheight = screentextureheight;
10528                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
10529                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
10530         }
10531         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
10532         {
10533                 if (r_bloomstate.texture_bloom)
10534                         R_FreeTexture(r_bloomstate.texture_bloom);
10535                 r_bloomstate.texture_bloom = NULL;
10536                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
10537                 r_bloomstate.bloomtextureheight = bloomtextureheight;
10538                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
10539                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
10540         }
10541
10542         // when doing a reduced render (HDR) we want to use a smaller area
10543         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
10544         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
10545         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
10546         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
10547         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
10548
10549         // set up a texcoord array for the full resolution screen image
10550         // (we have to keep this around to copy back during final render)
10551         r_bloomstate.screentexcoord2f[0] = 0;
10552         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
10553         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
10554         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
10555         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
10556         r_bloomstate.screentexcoord2f[5] = 0;
10557         r_bloomstate.screentexcoord2f[6] = 0;
10558         r_bloomstate.screentexcoord2f[7] = 0;
10559
10560         // set up a texcoord array for the reduced resolution bloom image
10561         // (which will be additive blended over the screen image)
10562         r_bloomstate.bloomtexcoord2f[0] = 0;
10563         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
10564         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
10565         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
10566         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
10567         r_bloomstate.bloomtexcoord2f[5] = 0;
10568         r_bloomstate.bloomtexcoord2f[6] = 0;
10569         r_bloomstate.bloomtexcoord2f[7] = 0;
10570
10571         switch(vid.renderpath)
10572         {
10573         case RENDERPATH_GL11:
10574         case RENDERPATH_GL13:
10575         case RENDERPATH_GL20:
10576         case RENDERPATH_CGGL:
10577         case RENDERPATH_SOFT:
10578         case RENDERPATH_GLES2:
10579                 break;
10580         case RENDERPATH_D3D9:
10581         case RENDERPATH_D3D10:
10582         case RENDERPATH_D3D11:
10583                 {
10584                         int i;
10585                         for (i = 0;i < 4;i++)
10586                         {
10587                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
10588                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
10589                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
10590                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
10591                         }
10592                 }
10593                 break;
10594         }
10595
10596         if (r_hdr.integer || r_bloom.integer)
10597         {
10598                 r_bloomstate.enabled = true;
10599                 r_bloomstate.hdr = r_hdr.integer != 0;
10600         }
10601
10602         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);
10603 }
10604
10605 void R_Bloom_CopyBloomTexture(float colorscale)
10606 {
10607         r_refdef.stats.bloom++;
10608
10609         // scale down screen texture to the bloom texture size
10610         CHECKGLERROR
10611         R_SetViewport(&r_bloomstate.viewport);
10612         GL_BlendFunc(GL_ONE, GL_ZERO);
10613         GL_Color(colorscale, colorscale, colorscale, 1);
10614         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
10615         switch(vid.renderpath)
10616         {
10617         case RENDERPATH_GL11:
10618         case RENDERPATH_GL13:
10619         case RENDERPATH_GL20:
10620         case RENDERPATH_CGGL:
10621         case RENDERPATH_SOFT:
10622         case RENDERPATH_GLES2:
10623                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
10624                 break;
10625         case RENDERPATH_D3D9:
10626         case RENDERPATH_D3D10:
10627         case RENDERPATH_D3D11:
10628                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
10629                 break;
10630         }
10631         // TODO: do boxfilter scale-down in shader?
10632         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
10633         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10634         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
10635
10636         // we now have a bloom image in the framebuffer
10637         // copy it into the bloom image texture for later processing
10638         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);
10639         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
10640 }
10641
10642 void R_Bloom_CopyHDRTexture(void)
10643 {
10644         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);
10645         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
10646 }
10647
10648 void R_Bloom_MakeTexture(void)
10649 {
10650         int x, range, dir;
10651         float xoffset, yoffset, r, brighten;
10652
10653         r_refdef.stats.bloom++;
10654
10655         R_ResetViewRendering2D();
10656
10657         // we have a bloom image in the framebuffer
10658         CHECKGLERROR
10659         R_SetViewport(&r_bloomstate.viewport);
10660
10661         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
10662         {
10663                 x *= 2;
10664                 r = bound(0, r_bloom_colorexponent.value / x, 1);
10665                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10666                 GL_Color(r,r,r,1);
10667                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
10668                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
10669                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10670                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
10671
10672                 // copy the vertically blurred bloom view to a texture
10673                 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);
10674                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
10675         }
10676
10677         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
10678         brighten = r_bloom_brighten.value;
10679         if (r_hdr.integer)
10680                 brighten *= r_hdr_range.value;
10681         brighten = sqrt(brighten);
10682         if(range >= 1)
10683                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
10684         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
10685
10686         for (dir = 0;dir < 2;dir++)
10687         {
10688                 // blend on at multiple vertical offsets to achieve a vertical blur
10689                 // TODO: do offset blends using GLSL
10690                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
10691                 GL_BlendFunc(GL_ONE, GL_ZERO);
10692                 for (x = -range;x <= range;x++)
10693                 {
10694                         if (!dir){xoffset = 0;yoffset = x;}
10695                         else {xoffset = x;yoffset = 0;}
10696                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
10697                         yoffset /= (float)r_bloomstate.bloomtextureheight;
10698                         // compute a texcoord array with the specified x and y offset
10699                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
10700                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
10701                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
10702                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
10703                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
10704                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
10705                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
10706                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
10707                         // this r value looks like a 'dot' particle, fading sharply to
10708                         // black at the edges
10709                         // (probably not realistic but looks good enough)
10710                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
10711                         //r = brighten/(range*2+1);
10712                         r = brighten / (range * 2 + 1);
10713                         if(range >= 1)
10714                                 r *= (1 - x*x/(float)(range*range));
10715                         GL_Color(r, r, r, 1);
10716                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
10717                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10718                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
10719                         GL_BlendFunc(GL_ONE, GL_ONE);
10720                 }
10721
10722                 // copy the vertically blurred bloom view to a texture
10723                 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);
10724                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
10725         }
10726 }
10727
10728 void R_HDR_RenderBloomTexture(void)
10729 {
10730         int oldwidth, oldheight;
10731         float oldcolorscale;
10732         qboolean oldwaterstate;
10733
10734         oldwaterstate = r_waterstate.enabled;
10735         oldcolorscale = r_refdef.view.colorscale;
10736         oldwidth = r_refdef.view.width;
10737         oldheight = r_refdef.view.height;
10738         r_refdef.view.width = r_bloomstate.bloomwidth;
10739         r_refdef.view.height = r_bloomstate.bloomheight;
10740
10741         if(r_hdr.integer < 2)
10742                 r_waterstate.enabled = false;
10743
10744         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
10745         // TODO: add exposure compensation features
10746         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
10747
10748         r_refdef.view.showdebug = false;
10749         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
10750
10751         R_ResetViewRendering3D();
10752
10753         R_ClearScreen(r_refdef.fogenabled);
10754         if (r_timereport_active)
10755                 R_TimeReport("HDRclear");
10756
10757         R_View_Update();
10758         if (r_timereport_active)
10759                 R_TimeReport("visibility");
10760
10761         // only do secondary renders with HDR if r_hdr is 2 or higher
10762         r_waterstate.numwaterplanes = 0;
10763         if (r_waterstate.enabled)
10764                 R_RenderWaterPlanes();
10765
10766         r_refdef.view.showdebug = true;
10767         R_RenderScene();
10768         r_waterstate.numwaterplanes = 0;
10769
10770         R_ResetViewRendering2D();
10771
10772         R_Bloom_CopyHDRTexture();
10773         R_Bloom_MakeTexture();
10774
10775         // restore the view settings
10776         r_waterstate.enabled = oldwaterstate;
10777         r_refdef.view.width = oldwidth;
10778         r_refdef.view.height = oldheight;
10779         r_refdef.view.colorscale = oldcolorscale;
10780
10781         R_ResetViewRendering3D();
10782
10783         R_ClearScreen(r_refdef.fogenabled);
10784         if (r_timereport_active)
10785                 R_TimeReport("viewclear");
10786 }
10787
10788 static void R_BlendView(void)
10789 {
10790         unsigned int permutation;
10791         float uservecs[4][4];
10792
10793         switch (vid.renderpath)
10794         {
10795         case RENDERPATH_GL20:
10796         case RENDERPATH_CGGL:
10797         case RENDERPATH_D3D9:
10798         case RENDERPATH_D3D10:
10799         case RENDERPATH_D3D11:
10800         case RENDERPATH_SOFT:
10801         case RENDERPATH_GLES2:
10802                 permutation =
10803                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
10804                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
10805                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
10806                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
10807                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
10808
10809                 if (r_bloomstate.texture_screen)
10810                 {
10811                         // make sure the buffer is available
10812                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
10813
10814                         R_ResetViewRendering2D();
10815
10816                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
10817                         {
10818                                 // declare variables
10819                                 float speed;
10820                                 static float avgspeed;
10821
10822                                 speed = VectorLength(cl.movement_velocity);
10823
10824                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
10825                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
10826
10827                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
10828                                 speed = bound(0, speed, 1);
10829                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
10830
10831                                 // calculate values into a standard alpha
10832                                 cl.motionbluralpha = 1 - exp(-
10833                                                 (
10834                                                  (r_motionblur.value * speed / 80)
10835                                                  +
10836                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
10837                                                 )
10838                                                 /
10839                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
10840                                            );
10841
10842                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
10843                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
10844                                 // apply the blur
10845                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
10846                                 {
10847                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10848                                         GL_Color(1, 1, 1, cl.motionbluralpha);
10849                                         switch(vid.renderpath)
10850                                         {
10851                                         case RENDERPATH_GL11:
10852                                         case RENDERPATH_GL13:
10853                                         case RENDERPATH_GL20:
10854                                         case RENDERPATH_CGGL:
10855                                         case RENDERPATH_SOFT:
10856                                         case RENDERPATH_GLES2:
10857                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
10858                                                 break;
10859                                         case RENDERPATH_D3D9:
10860                                         case RENDERPATH_D3D10:
10861                                         case RENDERPATH_D3D11:
10862                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
10863                                                 break;
10864                                         }
10865                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
10866                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10867                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
10868                                 }
10869                         }
10870
10871                         // copy view into the screen texture
10872                         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);
10873                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
10874                 }
10875                 else if (!r_bloomstate.texture_bloom)
10876                 {
10877                         // we may still have to do view tint...
10878                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
10879                         {
10880                                 // apply a color tint to the whole view
10881                                 R_ResetViewRendering2D();
10882                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
10883                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
10884                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10885                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10886                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10887                         }
10888                         break; // no screen processing, no bloom, skip it
10889                 }
10890
10891                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
10892                 {
10893                         // render simple bloom effect
10894                         // copy the screen and shrink it and darken it for the bloom process
10895                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
10896                         // make the bloom texture
10897                         R_Bloom_MakeTexture();
10898                 }
10899
10900 #if _MSC_VER >= 1400
10901 #define sscanf sscanf_s
10902 #endif
10903                 memset(uservecs, 0, sizeof(uservecs));
10904                 if (r_glsl_postprocess_uservec1_enable.integer)
10905                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
10906                 if (r_glsl_postprocess_uservec2_enable.integer)
10907                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
10908                 if (r_glsl_postprocess_uservec3_enable.integer)
10909                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
10910                 if (r_glsl_postprocess_uservec4_enable.integer)
10911                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
10912
10913                 R_ResetViewRendering2D();
10914                 GL_Color(1, 1, 1, 1);
10915                 GL_BlendFunc(GL_ONE, GL_ZERO);
10916
10917                 switch(vid.renderpath)
10918                 {
10919                 case RENDERPATH_GL20:
10920                 case RENDERPATH_GLES2:
10921                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
10922                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
10923                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
10924                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
10925                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
10926                         if (r_glsl_permutation->loc_ViewTintColor           >= 0) qglUniform4f(r_glsl_permutation->loc_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
10927                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
10928                         if (r_glsl_permutation->loc_UserVec1                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
10929                         if (r_glsl_permutation->loc_UserVec2                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
10930                         if (r_glsl_permutation->loc_UserVec3                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
10931                         if (r_glsl_permutation->loc_UserVec4                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
10932                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
10933                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
10934                         if (r_glsl_permutation->loc_BloomColorSubtract      >= 0) qglUniform4f(r_glsl_permutation->loc_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
10935                         break;
10936                 case RENDERPATH_CGGL:
10937 #ifdef SUPPORTCG
10938                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
10939                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
10940                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
10941                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
10942                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
10943                         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
10944                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
10945                         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
10946                         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
10947                         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
10948                         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
10949                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
10950                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
10951                         if (r_cg_permutation->fp_BloomColorSubtract   ) cgGLSetParameter4f(r_cg_permutation->fp_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
10952 #endif
10953                         break;
10954                 case RENDERPATH_D3D9:
10955 #ifdef SUPPORTD3D
10956                         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
10957                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
10958                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
10959                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
10960                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
10961                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
10962                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
10963                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
10964                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
10965                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
10966                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
10967                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
10968                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
10969                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
10970                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
10971 #endif
10972                         break;
10973                 case RENDERPATH_D3D10:
10974                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10975                         break;
10976                 case RENDERPATH_D3D11:
10977                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10978                         break;
10979                 case RENDERPATH_SOFT:
10980                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
10981                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
10982                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
10983                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
10984                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
10985                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
10986                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
10987                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
10988                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
10989                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
10990                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
10991                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
10992                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
10993                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
10994                         break;
10995                 default:
10996                         break;
10997                 }
10998                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10999                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
11000                 break;
11001         case RENDERPATH_GL13:
11002         case RENDERPATH_GL11:
11003                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
11004                 {
11005                         // apply a color tint to the whole view
11006                         R_ResetViewRendering2D();
11007                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
11008                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
11009                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11010                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11011                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11012                 }
11013                 break;
11014         }
11015 }
11016
11017 matrix4x4_t r_waterscrollmatrix;
11018
11019 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
11020 {
11021         if (r_refdef.fog_density)
11022         {
11023                 r_refdef.fogcolor[0] = r_refdef.fog_red;
11024                 r_refdef.fogcolor[1] = r_refdef.fog_green;
11025                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
11026
11027                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
11028                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
11029                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
11030                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
11031
11032                 {
11033                         vec3_t fogvec;
11034                         VectorCopy(r_refdef.fogcolor, fogvec);
11035                         //   color.rgb *= ContrastBoost * SceneBrightness;
11036                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
11037                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
11038                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
11039                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
11040                 }
11041         }
11042 }
11043
11044 void R_UpdateVariables(void)
11045 {
11046         R_Textures_Frame();
11047
11048         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
11049
11050         r_refdef.farclip = r_farclip_base.value;
11051         if (r_refdef.scene.worldmodel)
11052                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
11053         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
11054
11055         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
11056                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
11057         r_refdef.polygonfactor = 0;
11058         r_refdef.polygonoffset = 0;
11059         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
11060         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
11061
11062         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
11063         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
11064         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
11065         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
11066         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
11067         if (FAKELIGHT_ENABLED)
11068         {
11069                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
11070         }
11071         if (r_showsurfaces.integer)
11072         {
11073                 r_refdef.scene.rtworld = false;
11074                 r_refdef.scene.rtworldshadows = false;
11075                 r_refdef.scene.rtdlight = false;
11076                 r_refdef.scene.rtdlightshadows = false;
11077                 r_refdef.lightmapintensity = 0;
11078         }
11079
11080         if (gamemode == GAME_NEHAHRA)
11081         {
11082                 if (gl_fogenable.integer)
11083                 {
11084                         r_refdef.oldgl_fogenable = true;
11085                         r_refdef.fog_density = gl_fogdensity.value;
11086                         r_refdef.fog_red = gl_fogred.value;
11087                         r_refdef.fog_green = gl_foggreen.value;
11088                         r_refdef.fog_blue = gl_fogblue.value;
11089                         r_refdef.fog_alpha = 1;
11090                         r_refdef.fog_start = 0;
11091                         r_refdef.fog_end = gl_skyclip.value;
11092                         r_refdef.fog_height = 1<<30;
11093                         r_refdef.fog_fadedepth = 128;
11094                 }
11095                 else if (r_refdef.oldgl_fogenable)
11096                 {
11097                         r_refdef.oldgl_fogenable = false;
11098                         r_refdef.fog_density = 0;
11099                         r_refdef.fog_red = 0;
11100                         r_refdef.fog_green = 0;
11101                         r_refdef.fog_blue = 0;
11102                         r_refdef.fog_alpha = 0;
11103                         r_refdef.fog_start = 0;
11104                         r_refdef.fog_end = 0;
11105                         r_refdef.fog_height = 1<<30;
11106                         r_refdef.fog_fadedepth = 128;
11107                 }
11108         }
11109
11110         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
11111         r_refdef.fog_start = max(0, r_refdef.fog_start);
11112         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
11113
11114         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
11115
11116         if (r_refdef.fog_density && r_drawfog.integer)
11117         {
11118                 r_refdef.fogenabled = true;
11119                 // this is the point where the fog reaches 0.9986 alpha, which we
11120                 // consider a good enough cutoff point for the texture
11121                 // (0.9986 * 256 == 255.6)
11122                 if (r_fog_exp2.integer)
11123                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
11124                 else
11125                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
11126                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
11127                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
11128                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
11129                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
11130                         R_BuildFogHeightTexture();
11131                 // fog color was already set
11132                 // update the fog texture
11133                 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)
11134                         R_BuildFogTexture();
11135                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
11136                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
11137         }
11138         else
11139                 r_refdef.fogenabled = false;
11140
11141         switch(vid.renderpath)
11142         {
11143         case RENDERPATH_GL20:
11144         case RENDERPATH_CGGL:
11145         case RENDERPATH_D3D9:
11146         case RENDERPATH_D3D10:
11147         case RENDERPATH_D3D11:
11148         case RENDERPATH_SOFT:
11149         case RENDERPATH_GLES2:
11150                 if(v_glslgamma.integer && !vid_gammatables_trivial)
11151                 {
11152                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
11153                         {
11154                                 // build GLSL gamma texture
11155 #define RAMPWIDTH 256
11156                                 unsigned short ramp[RAMPWIDTH * 3];
11157                                 unsigned char rampbgr[RAMPWIDTH][4];
11158                                 int i;
11159
11160                                 r_texture_gammaramps_serial = vid_gammatables_serial;
11161
11162                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
11163                                 for(i = 0; i < RAMPWIDTH; ++i)
11164                                 {
11165                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
11166                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
11167                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
11168                                         rampbgr[i][3] = 0;
11169                                 }
11170                                 if (r_texture_gammaramps)
11171                                 {
11172                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
11173                                 }
11174                                 else
11175                                 {
11176                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
11177                                 }
11178                         }
11179                 }
11180                 else
11181                 {
11182                         // remove GLSL gamma texture
11183                 }
11184                 break;
11185         case RENDERPATH_GL13:
11186         case RENDERPATH_GL11:
11187                 break;
11188         }
11189 }
11190
11191 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
11192 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
11193 /*
11194 ================
11195 R_SelectScene
11196 ================
11197 */
11198 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
11199         if( scenetype != r_currentscenetype ) {
11200                 // store the old scenetype
11201                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
11202                 r_currentscenetype = scenetype;
11203                 // move in the new scene
11204                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
11205         }
11206 }
11207
11208 /*
11209 ================
11210 R_GetScenePointer
11211 ================
11212 */
11213 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
11214 {
11215         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
11216         if( scenetype == r_currentscenetype ) {
11217                 return &r_refdef.scene;
11218         } else {
11219                 return &r_scenes_store[ scenetype ];
11220         }
11221 }
11222
11223 /*
11224 ================
11225 R_RenderView
11226 ================
11227 */
11228 int dpsoftrast_test;
11229 void R_RenderView(void)
11230 {
11231         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
11232
11233         dpsoftrast_test = r_test.integer;
11234
11235         if (r_timereport_active)
11236                 R_TimeReport("start");
11237         r_textureframe++; // used only by R_GetCurrentTexture
11238         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11239
11240         if(R_CompileShader_CheckStaticParms())
11241                 R_GLSL_Restart_f();
11242
11243         if (!r_drawentities.integer)
11244                 r_refdef.scene.numentities = 0;
11245
11246         R_AnimCache_ClearCache();
11247         R_FrameData_NewFrame();
11248
11249         /* adjust for stereo display */
11250         if(R_Stereo_Active())
11251         {
11252                 Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_separation.value * (0.5f - r_stereo_side), 0, 0, r_stereo_angle.value * (0.5f - r_stereo_side), 0, 1);
11253                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
11254         }
11255
11256         if (r_refdef.view.isoverlay)
11257         {
11258                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
11259                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
11260                 R_TimeReport("depthclear");
11261
11262                 r_refdef.view.showdebug = false;
11263
11264                 r_waterstate.enabled = false;
11265                 r_waterstate.numwaterplanes = 0;
11266
11267                 R_RenderScene();
11268
11269                 r_refdef.view.matrix = originalmatrix;
11270
11271                 CHECKGLERROR
11272                 return;
11273         }
11274
11275         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
11276         {
11277                 r_refdef.view.matrix = originalmatrix;
11278                 return; //Host_Error ("R_RenderView: NULL worldmodel");
11279         }
11280
11281         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
11282
11283         R_RenderView_UpdateViewVectors();
11284
11285         R_Shadow_UpdateWorldLightSelection();
11286
11287         R_Bloom_StartFrame();
11288         R_Water_StartFrame();
11289
11290         CHECKGLERROR
11291         if (r_timereport_active)
11292                 R_TimeReport("viewsetup");
11293
11294         R_ResetViewRendering3D();
11295
11296         if (r_refdef.view.clear || r_refdef.fogenabled)
11297         {
11298                 R_ClearScreen(r_refdef.fogenabled);
11299                 if (r_timereport_active)
11300                         R_TimeReport("viewclear");
11301         }
11302         r_refdef.view.clear = true;
11303
11304         // this produces a bloom texture to be used in R_BlendView() later
11305         if (r_hdr.integer && r_bloomstate.bloomwidth)
11306         {
11307                 R_HDR_RenderBloomTexture();
11308                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
11309                 r_textureframe++; // used only by R_GetCurrentTexture
11310         }
11311
11312         r_refdef.view.showdebug = true;
11313
11314         R_View_Update();
11315         if (r_timereport_active)
11316                 R_TimeReport("visibility");
11317
11318         r_waterstate.numwaterplanes = 0;
11319         if (r_waterstate.enabled)
11320                 R_RenderWaterPlanes();
11321
11322         R_RenderScene();
11323         r_waterstate.numwaterplanes = 0;
11324
11325         R_BlendView();
11326         if (r_timereport_active)
11327                 R_TimeReport("blendview");
11328
11329         GL_Scissor(0, 0, vid.width, vid.height);
11330         GL_ScissorTest(false);
11331
11332         r_refdef.view.matrix = originalmatrix;
11333
11334         CHECKGLERROR
11335 }
11336
11337 void R_RenderWaterPlanes(void)
11338 {
11339         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
11340         {
11341                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
11342                 if (r_timereport_active)
11343                         R_TimeReport("waterworld");
11344         }
11345
11346         // don't let sound skip if going slow
11347         if (r_refdef.scene.extraupdate)
11348                 S_ExtraUpdate ();
11349
11350         R_DrawModelsAddWaterPlanes();
11351         if (r_timereport_active)
11352                 R_TimeReport("watermodels");
11353
11354         if (r_waterstate.numwaterplanes)
11355         {
11356                 R_Water_ProcessPlanes();
11357                 if (r_timereport_active)
11358                         R_TimeReport("waterscenes");
11359         }
11360 }
11361
11362 extern void R_DrawLightningBeams (void);
11363 extern void VM_CL_AddPolygonsToMeshQueue (void);
11364 extern void R_DrawPortals (void);
11365 extern cvar_t cl_locs_show;
11366 static void R_DrawLocs(void);
11367 static void R_DrawEntityBBoxes(void);
11368 static void R_DrawModelDecals(void);
11369 extern void R_DrawModelShadows(void);
11370 extern void R_DrawModelShadowMaps(void);
11371 extern cvar_t cl_decals_newsystem;
11372 extern qboolean r_shadow_usingdeferredprepass;
11373 void R_RenderScene(void)
11374 {
11375         qboolean shadowmapping = false;
11376
11377         if (r_timereport_active)
11378                 R_TimeReport("beginscene");
11379
11380         r_refdef.stats.renders++;
11381
11382         R_UpdateFogColor();
11383
11384         // don't let sound skip if going slow
11385         if (r_refdef.scene.extraupdate)
11386                 S_ExtraUpdate ();
11387
11388         R_MeshQueue_BeginScene();
11389
11390         R_SkyStartFrame();
11391
11392         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);
11393
11394         if (r_timereport_active)
11395                 R_TimeReport("skystartframe");
11396
11397         if (cl.csqc_vidvars.drawworld)
11398         {
11399                 // don't let sound skip if going slow
11400                 if (r_refdef.scene.extraupdate)
11401                         S_ExtraUpdate ();
11402
11403                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
11404                 {
11405                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
11406                         if (r_timereport_active)
11407                                 R_TimeReport("worldsky");
11408                 }
11409
11410                 if (R_DrawBrushModelsSky() && r_timereport_active)
11411                         R_TimeReport("bmodelsky");
11412
11413                 if (skyrendermasked && skyrenderlater)
11414                 {
11415                         // we have to force off the water clipping plane while rendering sky
11416                         R_SetupView(false);
11417                         R_Sky();
11418                         R_SetupView(true);
11419                         if (r_timereport_active)
11420                                 R_TimeReport("sky");
11421                 }
11422         }
11423
11424         R_AnimCache_CacheVisibleEntities();
11425         if (r_timereport_active)
11426                 R_TimeReport("animation");
11427
11428         R_Shadow_PrepareLights();
11429         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
11430                 R_Shadow_PrepareModelShadows();
11431         if (r_timereport_active)
11432                 R_TimeReport("preparelights");
11433
11434         if (R_Shadow_ShadowMappingEnabled())
11435                 shadowmapping = true;
11436
11437         if (r_shadow_usingdeferredprepass)
11438                 R_Shadow_DrawPrepass();
11439
11440         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
11441         {
11442                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
11443                 if (r_timereport_active)
11444                         R_TimeReport("worlddepth");
11445         }
11446         if (r_depthfirst.integer >= 2)
11447         {
11448                 R_DrawModelsDepth();
11449                 if (r_timereport_active)
11450                         R_TimeReport("modeldepth");
11451         }
11452
11453         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
11454         {
11455                 R_DrawModelShadowMaps();
11456                 R_ResetViewRendering3D();
11457                 // don't let sound skip if going slow
11458                 if (r_refdef.scene.extraupdate)
11459                         S_ExtraUpdate ();
11460         }
11461
11462         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
11463         {
11464                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
11465                 if (r_timereport_active)
11466                         R_TimeReport("world");
11467         }
11468
11469         // don't let sound skip if going slow
11470         if (r_refdef.scene.extraupdate)
11471                 S_ExtraUpdate ();
11472
11473         R_DrawModels();
11474         if (r_timereport_active)
11475                 R_TimeReport("models");
11476
11477         // don't let sound skip if going slow
11478         if (r_refdef.scene.extraupdate)
11479                 S_ExtraUpdate ();
11480
11481         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
11482         {
11483                 R_DrawModelShadows();
11484                 R_ResetViewRendering3D();
11485                 // don't let sound skip if going slow
11486                 if (r_refdef.scene.extraupdate)
11487                         S_ExtraUpdate ();
11488         }
11489
11490         if (!r_shadow_usingdeferredprepass)
11491         {
11492                 R_Shadow_DrawLights();
11493                 if (r_timereport_active)
11494                         R_TimeReport("rtlights");
11495         }
11496
11497         // don't let sound skip if going slow
11498         if (r_refdef.scene.extraupdate)
11499                 S_ExtraUpdate ();
11500
11501         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
11502         {
11503                 R_DrawModelShadows();
11504                 R_ResetViewRendering3D();
11505                 // don't let sound skip if going slow
11506                 if (r_refdef.scene.extraupdate)
11507                         S_ExtraUpdate ();
11508         }
11509
11510         if (cl.csqc_vidvars.drawworld)
11511         {
11512                 if (cl_decals_newsystem.integer)
11513                 {
11514                         R_DrawModelDecals();
11515                         if (r_timereport_active)
11516                                 R_TimeReport("modeldecals");
11517                 }
11518                 else
11519                 {
11520                         R_DrawDecals();
11521                         if (r_timereport_active)
11522                                 R_TimeReport("decals");
11523                 }
11524
11525                 R_DrawParticles();
11526                 if (r_timereport_active)
11527                         R_TimeReport("particles");
11528
11529                 R_DrawExplosions();
11530                 if (r_timereport_active)
11531                         R_TimeReport("explosions");
11532
11533                 R_DrawLightningBeams();
11534                 if (r_timereport_active)
11535                         R_TimeReport("lightning");
11536         }
11537
11538         VM_CL_AddPolygonsToMeshQueue();
11539
11540         if (r_refdef.view.showdebug)
11541         {
11542                 if (cl_locs_show.integer)
11543                 {
11544                         R_DrawLocs();
11545                         if (r_timereport_active)
11546                                 R_TimeReport("showlocs");
11547                 }
11548
11549                 if (r_drawportals.integer)
11550                 {
11551                         R_DrawPortals();
11552                         if (r_timereport_active)
11553                                 R_TimeReport("portals");
11554                 }
11555
11556                 if (r_showbboxes.value > 0)
11557                 {
11558                         R_DrawEntityBBoxes();
11559                         if (r_timereport_active)
11560                                 R_TimeReport("bboxes");
11561                 }
11562         }
11563
11564         R_MeshQueue_RenderTransparent();
11565         if (r_timereport_active)
11566                 R_TimeReport("drawtrans");
11567
11568         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))
11569         {
11570                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
11571                 if (r_timereport_active)
11572                         R_TimeReport("worlddebug");
11573                 R_DrawModelsDebug();
11574                 if (r_timereport_active)
11575                         R_TimeReport("modeldebug");
11576         }
11577
11578         if (cl.csqc_vidvars.drawworld)
11579         {
11580                 R_Shadow_DrawCoronas();
11581                 if (r_timereport_active)
11582                         R_TimeReport("coronas");
11583         }
11584
11585 #if 0
11586         {
11587                 GL_DepthTest(false);
11588                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11589                 GL_Color(1, 1, 1, 1);
11590                 qglBegin(GL_POLYGON);
11591                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
11592                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
11593                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
11594                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
11595                 qglEnd();
11596                 qglBegin(GL_POLYGON);
11597                 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]);
11598                 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]);
11599                 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]);
11600                 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]);
11601                 qglEnd();
11602                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11603         }
11604 #endif
11605
11606         // don't let sound skip if going slow
11607         if (r_refdef.scene.extraupdate)
11608                 S_ExtraUpdate ();
11609
11610         R_ResetViewRendering2D();
11611 }
11612
11613 static const unsigned short bboxelements[36] =
11614 {
11615         5, 1, 3, 5, 3, 7,
11616         6, 2, 0, 6, 0, 4,
11617         7, 3, 2, 7, 2, 6,
11618         4, 0, 1, 4, 1, 5,
11619         4, 5, 7, 4, 7, 6,
11620         1, 0, 2, 1, 2, 3,
11621 };
11622
11623 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
11624 {
11625         int i;
11626         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
11627
11628         RSurf_ActiveWorldEntity();
11629
11630         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11631         GL_DepthMask(false);
11632         GL_DepthRange(0, 1);
11633         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11634 //      R_Mesh_ResetTextureState();
11635
11636         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
11637         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
11638         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
11639         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
11640         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
11641         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
11642         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
11643         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
11644         R_FillColors(color4f, 8, cr, cg, cb, ca);
11645         if (r_refdef.fogenabled)
11646         {
11647                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
11648                 {
11649                         f1 = RSurf_FogVertex(v);
11650                         f2 = 1 - f1;
11651                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
11652                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
11653                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
11654                 }
11655         }
11656         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
11657         R_Mesh_ResetTextureState();
11658         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11659         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
11660 }
11661
11662 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11663 {
11664         int i;
11665         float color[4];
11666         prvm_edict_t *edict;
11667         prvm_prog_t *prog_save = prog;
11668
11669         // this function draws bounding boxes of server entities
11670         if (!sv.active)
11671                 return;
11672
11673         GL_CullFace(GL_NONE);
11674         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11675
11676         prog = 0;
11677         SV_VM_Begin();
11678         for (i = 0;i < numsurfaces;i++)
11679         {
11680                 edict = PRVM_EDICT_NUM(surfacelist[i]);
11681                 switch ((int)edict->fields.server->solid)
11682                 {
11683                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
11684                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
11685                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
11686                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
11687                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
11688                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
11689                 }
11690                 color[3] *= r_showbboxes.value;
11691                 color[3] = bound(0, color[3], 1);
11692                 GL_DepthTest(!r_showdisabledepthtest.integer);
11693                 GL_CullFace(r_refdef.view.cullface_front);
11694                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
11695         }
11696         SV_VM_End();
11697         prog = prog_save;
11698 }
11699
11700 static void R_DrawEntityBBoxes(void)
11701 {
11702         int i;
11703         prvm_edict_t *edict;
11704         vec3_t center;
11705         prvm_prog_t *prog_save = prog;
11706
11707         // this function draws bounding boxes of server entities
11708         if (!sv.active)
11709                 return;
11710
11711         prog = 0;
11712         SV_VM_Begin();
11713         for (i = 0;i < prog->num_edicts;i++)
11714         {
11715                 edict = PRVM_EDICT_NUM(i);
11716                 if (edict->priv.server->free)
11717                         continue;
11718                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
11719                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
11720                         continue;
11721                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
11722                         continue;
11723                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
11724                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
11725         }
11726         SV_VM_End();
11727         prog = prog_save;
11728 }
11729
11730 static const int nomodelelement3i[24] =
11731 {
11732         5, 2, 0,
11733         5, 1, 2,
11734         5, 0, 3,
11735         5, 3, 1,
11736         0, 2, 4,
11737         2, 1, 4,
11738         3, 0, 4,
11739         1, 3, 4
11740 };
11741
11742 static const unsigned short nomodelelement3s[24] =
11743 {
11744         5, 2, 0,
11745         5, 1, 2,
11746         5, 0, 3,
11747         5, 3, 1,
11748         0, 2, 4,
11749         2, 1, 4,
11750         3, 0, 4,
11751         1, 3, 4
11752 };
11753
11754 static const float nomodelvertex3f[6*3] =
11755 {
11756         -16,   0,   0,
11757          16,   0,   0,
11758           0, -16,   0,
11759           0,  16,   0,
11760           0,   0, -16,
11761           0,   0,  16
11762 };
11763
11764 static const float nomodelcolor4f[6*4] =
11765 {
11766         0.0f, 0.0f, 0.5f, 1.0f,
11767         0.0f, 0.0f, 0.5f, 1.0f,
11768         0.0f, 0.5f, 0.0f, 1.0f,
11769         0.0f, 0.5f, 0.0f, 1.0f,
11770         0.5f, 0.0f, 0.0f, 1.0f,
11771         0.5f, 0.0f, 0.0f, 1.0f
11772 };
11773
11774 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11775 {
11776         int i;
11777         float f1, f2, *c;
11778         float color4f[6*4];
11779
11780         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);
11781
11782         // this is only called once per entity so numsurfaces is always 1, and
11783         // surfacelist is always {0}, so this code does not handle batches
11784
11785         if (rsurface.ent_flags & RENDER_ADDITIVE)
11786         {
11787                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
11788                 GL_DepthMask(false);
11789         }
11790         else if (rsurface.colormod[3] < 1)
11791         {
11792                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11793                 GL_DepthMask(false);
11794         }
11795         else
11796         {
11797                 GL_BlendFunc(GL_ONE, GL_ZERO);
11798                 GL_DepthMask(true);
11799         }
11800         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
11801         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
11802         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
11803         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
11804         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
11805         for (i = 0, c = color4f;i < 6;i++, c += 4)
11806         {
11807                 c[0] *= rsurface.colormod[0];
11808                 c[1] *= rsurface.colormod[1];
11809                 c[2] *= rsurface.colormod[2];
11810                 c[3] *= rsurface.colormod[3];
11811         }
11812         if (r_refdef.fogenabled)
11813         {
11814                 for (i = 0, c = color4f;i < 6;i++, c += 4)
11815                 {
11816                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
11817                         f2 = 1 - f1;
11818                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
11819                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
11820                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
11821                 }
11822         }
11823 //      R_Mesh_ResetTextureState();
11824         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11825         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
11826         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
11827 }
11828
11829 void R_DrawNoModel(entity_render_t *ent)
11830 {
11831         vec3_t org;
11832         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
11833         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
11834                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
11835         else
11836                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
11837 }
11838
11839 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
11840 {
11841         vec3_t right1, right2, diff, normal;
11842
11843         VectorSubtract (org2, org1, normal);
11844
11845         // calculate 'right' vector for start
11846         VectorSubtract (r_refdef.view.origin, org1, diff);
11847         CrossProduct (normal, diff, right1);
11848         VectorNormalize (right1);
11849
11850         // calculate 'right' vector for end
11851         VectorSubtract (r_refdef.view.origin, org2, diff);
11852         CrossProduct (normal, diff, right2);
11853         VectorNormalize (right2);
11854
11855         vert[ 0] = org1[0] + width * right1[0];
11856         vert[ 1] = org1[1] + width * right1[1];
11857         vert[ 2] = org1[2] + width * right1[2];
11858         vert[ 3] = org1[0] - width * right1[0];
11859         vert[ 4] = org1[1] - width * right1[1];
11860         vert[ 5] = org1[2] - width * right1[2];
11861         vert[ 6] = org2[0] - width * right2[0];
11862         vert[ 7] = org2[1] - width * right2[1];
11863         vert[ 8] = org2[2] - width * right2[2];
11864         vert[ 9] = org2[0] + width * right2[0];
11865         vert[10] = org2[1] + width * right2[1];
11866         vert[11] = org2[2] + width * right2[2];
11867 }
11868
11869 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)
11870 {
11871         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
11872         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
11873         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
11874         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
11875         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
11876         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
11877         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
11878         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
11879         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
11880         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
11881         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
11882         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
11883 }
11884
11885 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
11886 {
11887         int i;
11888         float *vertex3f;
11889         float v[3];
11890         VectorSet(v, x, y, z);
11891         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
11892                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
11893                         break;
11894         if (i == mesh->numvertices)
11895         {
11896                 if (mesh->numvertices < mesh->maxvertices)
11897                 {
11898                         VectorCopy(v, vertex3f);
11899                         mesh->numvertices++;
11900                 }
11901                 return mesh->numvertices;
11902         }
11903         else
11904                 return i;
11905 }
11906
11907 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
11908 {
11909         int i;
11910         int *e, element[3];
11911         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
11912         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
11913         e = mesh->element3i + mesh->numtriangles * 3;
11914         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
11915         {
11916                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
11917                 if (mesh->numtriangles < mesh->maxtriangles)
11918                 {
11919                         *e++ = element[0];
11920                         *e++ = element[1];
11921                         *e++ = element[2];
11922                         mesh->numtriangles++;
11923                 }
11924                 element[1] = element[2];
11925         }
11926 }
11927
11928 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
11929 {
11930         int i;
11931         int *e, element[3];
11932         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
11933         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
11934         e = mesh->element3i + mesh->numtriangles * 3;
11935         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
11936         {
11937                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
11938                 if (mesh->numtriangles < mesh->maxtriangles)
11939                 {
11940                         *e++ = element[0];
11941                         *e++ = element[1];
11942                         *e++ = element[2];
11943                         mesh->numtriangles++;
11944                 }
11945                 element[1] = element[2];
11946         }
11947 }
11948
11949 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
11950 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
11951 {
11952         int planenum, planenum2;
11953         int w;
11954         int tempnumpoints;
11955         mplane_t *plane, *plane2;
11956         double maxdist;
11957         double temppoints[2][256*3];
11958         // figure out how large a bounding box we need to properly compute this brush
11959         maxdist = 0;
11960         for (w = 0;w < numplanes;w++)
11961                 maxdist = max(maxdist, fabs(planes[w].dist));
11962         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
11963         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
11964         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
11965         {
11966                 w = 0;
11967                 tempnumpoints = 4;
11968                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
11969                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
11970                 {
11971                         if (planenum2 == planenum)
11972                                 continue;
11973                         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);
11974                         w = !w;
11975                 }
11976                 if (tempnumpoints < 3)
11977                         continue;
11978                 // generate elements forming a triangle fan for this polygon
11979                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
11980         }
11981 }
11982
11983 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)
11984 {
11985         texturelayer_t *layer;
11986         layer = t->currentlayers + t->currentnumlayers++;
11987         layer->type = type;
11988         layer->depthmask = depthmask;
11989         layer->blendfunc1 = blendfunc1;
11990         layer->blendfunc2 = blendfunc2;
11991         layer->texture = texture;
11992         layer->texmatrix = *matrix;
11993         layer->color[0] = r;
11994         layer->color[1] = g;
11995         layer->color[2] = b;
11996         layer->color[3] = a;
11997 }
11998
11999 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
12000 {
12001         if(parms[0] == 0 && parms[1] == 0)
12002                 return false;
12003         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
12004                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
12005                         return false;
12006         return true;
12007 }
12008
12009 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
12010 {
12011         double index, f;
12012         index = parms[2] + r_refdef.scene.time * parms[3];
12013         index -= floor(index);
12014         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
12015         {
12016         default:
12017         case Q3WAVEFUNC_NONE:
12018         case Q3WAVEFUNC_NOISE:
12019         case Q3WAVEFUNC_COUNT:
12020                 f = 0;
12021                 break;
12022         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
12023         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
12024         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
12025         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
12026         case Q3WAVEFUNC_TRIANGLE:
12027                 index *= 4;
12028                 f = index - floor(index);
12029                 if (index < 1)
12030                         f = f;
12031                 else if (index < 2)
12032                         f = 1 - f;
12033                 else if (index < 3)
12034                         f = -f;
12035                 else
12036                         f = -(1 - f);
12037                 break;
12038         }
12039         f = parms[0] + parms[1] * f;
12040         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
12041                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
12042         return (float) f;
12043 }
12044
12045 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
12046 {
12047         int w, h, idx;
12048         float f;
12049         float tcmat[12];
12050         matrix4x4_t matrix, temp;
12051         switch(tcmod->tcmod)
12052         {
12053                 case Q3TCMOD_COUNT:
12054                 case Q3TCMOD_NONE:
12055                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
12056                                 matrix = r_waterscrollmatrix;
12057                         else
12058                                 matrix = identitymatrix;
12059                         break;
12060                 case Q3TCMOD_ENTITYTRANSLATE:
12061                         // this is used in Q3 to allow the gamecode to control texcoord
12062                         // scrolling on the entity, which is not supported in darkplaces yet.
12063                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
12064                         break;
12065                 case Q3TCMOD_ROTATE:
12066                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
12067                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
12068                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
12069                         break;
12070                 case Q3TCMOD_SCALE:
12071                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
12072                         break;
12073                 case Q3TCMOD_SCROLL:
12074                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
12075                         break;
12076                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
12077                         w = (int) tcmod->parms[0];
12078                         h = (int) tcmod->parms[1];
12079                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
12080                         f = f - floor(f);
12081                         idx = (int) floor(f * w * h);
12082                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
12083                         break;
12084                 case Q3TCMOD_STRETCH:
12085                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
12086                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
12087                         break;
12088                 case Q3TCMOD_TRANSFORM:
12089                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
12090                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
12091                         VectorSet(tcmat +  6, 0                   , 0                , 1);
12092                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
12093                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
12094                         break;
12095                 case Q3TCMOD_TURBULENT:
12096                         // this is handled in the RSurf_PrepareVertices function
12097                         matrix = identitymatrix;
12098                         break;
12099         }
12100         temp = *texmatrix;
12101         Matrix4x4_Concat(texmatrix, &matrix, &temp);
12102 }
12103
12104 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
12105 {
12106         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
12107         char name[MAX_QPATH];
12108         skinframe_t *skinframe;
12109         unsigned char pixels[296*194];
12110         strlcpy(cache->name, skinname, sizeof(cache->name));
12111         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
12112         if (developer_loading.integer)
12113                 Con_Printf("loading %s\n", name);
12114         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
12115         if (!skinframe || !skinframe->base)
12116         {
12117                 unsigned char *f;
12118                 fs_offset_t filesize;
12119                 skinframe = NULL;
12120                 f = FS_LoadFile(name, tempmempool, true, &filesize);
12121                 if (f)
12122                 {
12123                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
12124                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
12125                         Mem_Free(f);
12126                 }
12127         }
12128         cache->skinframe = skinframe;
12129 }
12130
12131 texture_t *R_GetCurrentTexture(texture_t *t)
12132 {
12133         int i;
12134         const entity_render_t *ent = rsurface.entity;
12135         dp_model_t *model = ent->model;
12136         q3shaderinfo_layer_tcmod_t *tcmod;
12137
12138         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
12139                 return t->currentframe;
12140         t->update_lastrenderframe = r_textureframe;
12141         t->update_lastrenderentity = (void *)ent;
12142
12143         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
12144                 t->camera_entity = ent->entitynumber;
12145         else
12146                 t->camera_entity = 0;
12147
12148         // switch to an alternate material if this is a q1bsp animated material
12149         {
12150                 texture_t *texture = t;
12151                 int s = rsurface.ent_skinnum;
12152                 if ((unsigned int)s >= (unsigned int)model->numskins)
12153                         s = 0;
12154                 if (model->skinscenes)
12155                 {
12156                         if (model->skinscenes[s].framecount > 1)
12157                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
12158                         else
12159                                 s = model->skinscenes[s].firstframe;
12160                 }
12161                 if (s > 0)
12162                         t = t + s * model->num_surfaces;
12163                 if (t->animated)
12164                 {
12165                         // use an alternate animation if the entity's frame is not 0,
12166                         // and only if the texture has an alternate animation
12167                         if (rsurface.ent_alttextures && t->anim_total[1])
12168                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
12169                         else
12170                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
12171                 }
12172                 texture->currentframe = t;
12173         }
12174
12175         // update currentskinframe to be a qw skin or animation frame
12176         if (rsurface.ent_qwskin >= 0)
12177         {
12178                 i = rsurface.ent_qwskin;
12179                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
12180                 {
12181                         r_qwskincache_size = cl.maxclients;
12182                         if (r_qwskincache)
12183                                 Mem_Free(r_qwskincache);
12184                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
12185                 }
12186                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
12187                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
12188                 t->currentskinframe = r_qwskincache[i].skinframe;
12189                 if (t->currentskinframe == NULL)
12190                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
12191         }
12192         else if (t->numskinframes >= 2)
12193                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
12194         if (t->backgroundnumskinframes >= 2)
12195                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
12196
12197         t->currentmaterialflags = t->basematerialflags;
12198         t->currentalpha = rsurface.colormod[3];
12199         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
12200                 t->currentalpha *= r_wateralpha.value;
12201         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
12202                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
12203         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
12204                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
12205         if (!(rsurface.ent_flags & RENDER_LIGHT))
12206                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
12207         else if (FAKELIGHT_ENABLED)
12208         {
12209                         // no modellight if using fakelight for the map
12210         }
12211         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
12212         {
12213                 // pick a model lighting mode
12214                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
12215                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
12216                 else
12217                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
12218         }
12219         if (rsurface.ent_flags & RENDER_ADDITIVE)
12220                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
12221         else if (t->currentalpha < 1)
12222                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
12223         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
12224                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
12225         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
12226                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
12227         if (t->backgroundnumskinframes)
12228                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
12229         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
12230         {
12231                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
12232                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
12233         }
12234         else
12235                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
12236         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
12237                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
12238
12239         // there is no tcmod
12240         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
12241         {
12242                 t->currenttexmatrix = r_waterscrollmatrix;
12243                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
12244         }
12245         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
12246         {
12247                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
12248                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
12249         }
12250
12251         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
12252                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
12253         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
12254                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
12255
12256         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
12257         if (t->currentskinframe->qpixels)
12258                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
12259         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
12260         if (!t->basetexture)
12261                 t->basetexture = r_texture_notexture;
12262         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
12263         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
12264         t->nmaptexture = t->currentskinframe->nmap;
12265         if (!t->nmaptexture)
12266                 t->nmaptexture = r_texture_blanknormalmap;
12267         t->glosstexture = r_texture_black;
12268         t->glowtexture = t->currentskinframe->glow;
12269         t->fogtexture = t->currentskinframe->fog;
12270         t->reflectmasktexture = t->currentskinframe->reflect;
12271         if (t->backgroundnumskinframes)
12272         {
12273                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
12274                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
12275                 t->backgroundglosstexture = r_texture_black;
12276                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
12277                 if (!t->backgroundnmaptexture)
12278                         t->backgroundnmaptexture = r_texture_blanknormalmap;
12279         }
12280         else
12281         {
12282                 t->backgroundbasetexture = r_texture_white;
12283                 t->backgroundnmaptexture = r_texture_blanknormalmap;
12284                 t->backgroundglosstexture = r_texture_black;
12285                 t->backgroundglowtexture = NULL;
12286         }
12287         t->specularpower = r_shadow_glossexponent.value;
12288         // TODO: store reference values for these in the texture?
12289         t->specularscale = 0;
12290         if (r_shadow_gloss.integer > 0)
12291         {
12292                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
12293                 {
12294                         if (r_shadow_glossintensity.value > 0)
12295                         {
12296                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
12297                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
12298                                 t->specularscale = r_shadow_glossintensity.value;
12299                         }
12300                 }
12301                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
12302                 {
12303                         t->glosstexture = r_texture_white;
12304                         t->backgroundglosstexture = r_texture_white;
12305                         t->specularscale = r_shadow_gloss2intensity.value;
12306                         t->specularpower = r_shadow_gloss2exponent.value;
12307                 }
12308         }
12309         t->specularscale *= t->specularscalemod;
12310         t->specularpower *= t->specularpowermod;
12311
12312         // lightmaps mode looks bad with dlights using actual texturing, so turn
12313         // off the colormap and glossmap, but leave the normalmap on as it still
12314         // accurately represents the shading involved
12315         if (gl_lightmaps.integer)
12316         {
12317                 t->basetexture = r_texture_grey128;
12318                 t->pantstexture = r_texture_black;
12319                 t->shirttexture = r_texture_black;
12320                 t->nmaptexture = r_texture_blanknormalmap;
12321                 t->glosstexture = r_texture_black;
12322                 t->glowtexture = NULL;
12323                 t->fogtexture = NULL;
12324                 t->reflectmasktexture = NULL;
12325                 t->backgroundbasetexture = NULL;
12326                 t->backgroundnmaptexture = r_texture_blanknormalmap;
12327                 t->backgroundglosstexture = r_texture_black;
12328                 t->backgroundglowtexture = NULL;
12329                 t->specularscale = 0;
12330                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
12331         }
12332
12333         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
12334         VectorClear(t->dlightcolor);
12335         t->currentnumlayers = 0;
12336         if (t->currentmaterialflags & MATERIALFLAG_WALL)
12337         {
12338                 int blendfunc1, blendfunc2;
12339                 qboolean depthmask;
12340                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
12341                 {
12342                         blendfunc1 = GL_SRC_ALPHA;
12343                         blendfunc2 = GL_ONE;
12344                 }
12345                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
12346                 {
12347                         blendfunc1 = GL_SRC_ALPHA;
12348                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
12349                 }
12350                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12351                 {
12352                         blendfunc1 = t->customblendfunc[0];
12353                         blendfunc2 = t->customblendfunc[1];
12354                 }
12355                 else
12356                 {
12357                         blendfunc1 = GL_ONE;
12358                         blendfunc2 = GL_ZERO;
12359                 }
12360                 // don't colormod evilblend textures
12361                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
12362                         VectorSet(t->lightmapcolor, 1, 1, 1);
12363                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
12364                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12365                 {
12366                         // fullbright is not affected by r_refdef.lightmapintensity
12367                         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]);
12368                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
12369                                 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]);
12370                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
12371                                 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]);
12372                 }
12373                 else
12374                 {
12375                         vec3_t ambientcolor;
12376                         float colorscale;
12377                         // set the color tint used for lights affecting this surface
12378                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
12379                         colorscale = 2;
12380                         // q3bsp has no lightmap updates, so the lightstylevalue that
12381                         // would normally be baked into the lightmap must be
12382                         // applied to the color
12383                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
12384                         if (model->type == mod_brushq3)
12385                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
12386                         colorscale *= r_refdef.lightmapintensity;
12387                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
12388                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
12389                         // basic lit geometry
12390                         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]);
12391                         // add pants/shirt if needed
12392                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
12393                                 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]);
12394                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
12395                                 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]);
12396                         // now add ambient passes if needed
12397                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
12398                         {
12399                                 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]);
12400                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
12401                                         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]);
12402                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
12403                                         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]);
12404                         }
12405                 }
12406                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
12407                         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]);
12408                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
12409                 {
12410                         // if this is opaque use alpha blend which will darken the earlier
12411                         // passes cheaply.
12412                         //
12413                         // if this is an alpha blended material, all the earlier passes
12414                         // were darkened by fog already, so we only need to add the fog
12415                         // color ontop through the fog mask texture
12416                         //
12417                         // if this is an additive blended material, all the earlier passes
12418                         // were darkened by fog already, and we should not add fog color
12419                         // (because the background was not darkened, there is no fog color
12420                         // that was lost behind it).
12421                         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]);
12422                 }
12423         }
12424
12425         return t->currentframe;
12426 }
12427
12428 rsurfacestate_t rsurface;
12429
12430 void RSurf_ActiveWorldEntity(void)
12431 {
12432         dp_model_t *model = r_refdef.scene.worldmodel;
12433         //if (rsurface.entity == r_refdef.scene.worldentity)
12434         //      return;
12435         rsurface.entity = r_refdef.scene.worldentity;
12436         rsurface.skeleton = NULL;
12437         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
12438         rsurface.ent_skinnum = 0;
12439         rsurface.ent_qwskin = -1;
12440         rsurface.ent_shadertime = 0;
12441         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
12442         rsurface.matrix = identitymatrix;
12443         rsurface.inversematrix = identitymatrix;
12444         rsurface.matrixscale = 1;
12445         rsurface.inversematrixscale = 1;
12446         R_EntityMatrix(&identitymatrix);
12447         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
12448         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
12449         rsurface.fograngerecip = r_refdef.fograngerecip;
12450         rsurface.fogheightfade = r_refdef.fogheightfade;
12451         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
12452         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
12453         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
12454         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
12455         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
12456         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
12457         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
12458         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
12459         rsurface.colormod[3] = 1;
12460         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);
12461         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
12462         rsurface.frameblend[0].lerp = 1;
12463         rsurface.ent_alttextures = false;
12464         rsurface.basepolygonfactor = r_refdef.polygonfactor;
12465         rsurface.basepolygonoffset = r_refdef.polygonoffset;
12466         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
12467         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12468         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
12469         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
12470         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12471         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
12472         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
12473         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12474         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
12475         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
12476         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12477         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
12478         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
12479         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12480         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
12481         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
12482         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12483         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
12484         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
12485         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12486         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
12487         rsurface.modelelement3i = model->surfmesh.data_element3i;
12488         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
12489         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
12490         rsurface.modelelement3s = model->surfmesh.data_element3s;
12491         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
12492         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
12493         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
12494         rsurface.modelnumvertices = model->surfmesh.num_vertices;
12495         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
12496         rsurface.modelsurfaces = model->data_surfaces;
12497         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
12498         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
12499         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
12500         rsurface.modelgeneratedvertex = false;
12501         rsurface.batchgeneratedvertex = false;
12502         rsurface.batchfirstvertex = 0;
12503         rsurface.batchnumvertices = 0;
12504         rsurface.batchfirsttriangle = 0;
12505         rsurface.batchnumtriangles = 0;
12506         rsurface.batchvertex3f  = NULL;
12507         rsurface.batchvertex3f_vertexbuffer = NULL;
12508         rsurface.batchvertex3f_bufferoffset = 0;
12509         rsurface.batchsvector3f = NULL;
12510         rsurface.batchsvector3f_vertexbuffer = NULL;
12511         rsurface.batchsvector3f_bufferoffset = 0;
12512         rsurface.batchtvector3f = NULL;
12513         rsurface.batchtvector3f_vertexbuffer = NULL;
12514         rsurface.batchtvector3f_bufferoffset = 0;
12515         rsurface.batchnormal3f  = NULL;
12516         rsurface.batchnormal3f_vertexbuffer = NULL;
12517         rsurface.batchnormal3f_bufferoffset = 0;
12518         rsurface.batchlightmapcolor4f = NULL;
12519         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
12520         rsurface.batchlightmapcolor4f_bufferoffset = 0;
12521         rsurface.batchtexcoordtexture2f = NULL;
12522         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12523         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12524         rsurface.batchtexcoordlightmap2f = NULL;
12525         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
12526         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
12527         rsurface.batchvertexmesh = NULL;
12528         rsurface.batchvertexmeshbuffer = NULL;
12529         rsurface.batchvertex3fbuffer = NULL;
12530         rsurface.batchelement3i = NULL;
12531         rsurface.batchelement3i_indexbuffer = NULL;
12532         rsurface.batchelement3i_bufferoffset = 0;
12533         rsurface.batchelement3s = NULL;
12534         rsurface.batchelement3s_indexbuffer = NULL;
12535         rsurface.batchelement3s_bufferoffset = 0;
12536         rsurface.passcolor4f = NULL;
12537         rsurface.passcolor4f_vertexbuffer = NULL;
12538         rsurface.passcolor4f_bufferoffset = 0;
12539 }
12540
12541 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
12542 {
12543         dp_model_t *model = ent->model;
12544         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
12545         //      return;
12546         rsurface.entity = (entity_render_t *)ent;
12547         rsurface.skeleton = ent->skeleton;
12548         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
12549         rsurface.ent_skinnum = ent->skinnum;
12550         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;
12551         rsurface.ent_shadertime = ent->shadertime;
12552         rsurface.ent_flags = ent->flags;
12553         rsurface.matrix = ent->matrix;
12554         rsurface.inversematrix = ent->inversematrix;
12555         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
12556         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
12557         R_EntityMatrix(&rsurface.matrix);
12558         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
12559         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
12560         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
12561         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
12562         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
12563         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
12564         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
12565         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
12566         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
12567         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
12568         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
12569         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
12570         rsurface.colormod[3] = ent->alpha;
12571         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
12572         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
12573         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
12574         rsurface.basepolygonfactor = r_refdef.polygonfactor;
12575         rsurface.basepolygonoffset = r_refdef.polygonoffset;
12576         if (ent->model->brush.submodel && !prepass)
12577         {
12578                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
12579                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
12580         }
12581         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
12582         {
12583                 if (ent->animcache_vertex3f)
12584                 {
12585                         rsurface.modelvertex3f = ent->animcache_vertex3f;
12586                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
12587                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
12588                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
12589                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
12590                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
12591                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
12592                 }
12593                 else if (wanttangents)
12594                 {
12595                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
12596                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
12597                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
12598                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
12599                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
12600                         rsurface.modelvertexmesh = NULL;
12601                         rsurface.modelvertexmeshbuffer = NULL;
12602                         rsurface.modelvertex3fbuffer = NULL;
12603                 }
12604                 else if (wantnormals)
12605                 {
12606                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
12607                         rsurface.modelsvector3f = NULL;
12608                         rsurface.modeltvector3f = NULL;
12609                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
12610                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
12611                         rsurface.modelvertexmesh = NULL;
12612                         rsurface.modelvertexmeshbuffer = NULL;
12613                         rsurface.modelvertex3fbuffer = NULL;
12614                 }
12615                 else
12616                 {
12617                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
12618                         rsurface.modelsvector3f = NULL;
12619                         rsurface.modeltvector3f = NULL;
12620                         rsurface.modelnormal3f = NULL;
12621                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
12622                         rsurface.modelvertexmesh = NULL;
12623                         rsurface.modelvertexmeshbuffer = NULL;
12624                         rsurface.modelvertex3fbuffer = NULL;
12625                 }
12626                 rsurface.modelvertex3f_vertexbuffer = 0;
12627                 rsurface.modelvertex3f_bufferoffset = 0;
12628                 rsurface.modelsvector3f_vertexbuffer = 0;
12629                 rsurface.modelsvector3f_bufferoffset = 0;
12630                 rsurface.modeltvector3f_vertexbuffer = 0;
12631                 rsurface.modeltvector3f_bufferoffset = 0;
12632                 rsurface.modelnormal3f_vertexbuffer = 0;
12633                 rsurface.modelnormal3f_bufferoffset = 0;
12634                 rsurface.modelgeneratedvertex = true;
12635         }
12636         else
12637         {
12638                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
12639                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12640                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
12641                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
12642                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12643                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
12644                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
12645                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12646                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
12647                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
12648                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12649                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
12650                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
12651                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
12652                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
12653                 rsurface.modelgeneratedvertex = false;
12654         }
12655         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
12656         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12657         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
12658         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
12659         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12660         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
12661         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
12662         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12663         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
12664         rsurface.modelelement3i = model->surfmesh.data_element3i;
12665         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
12666         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
12667         rsurface.modelelement3s = model->surfmesh.data_element3s;
12668         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
12669         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
12670         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
12671         rsurface.modelnumvertices = model->surfmesh.num_vertices;
12672         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
12673         rsurface.modelsurfaces = model->data_surfaces;
12674         rsurface.batchgeneratedvertex = false;
12675         rsurface.batchfirstvertex = 0;
12676         rsurface.batchnumvertices = 0;
12677         rsurface.batchfirsttriangle = 0;
12678         rsurface.batchnumtriangles = 0;
12679         rsurface.batchvertex3f  = NULL;
12680         rsurface.batchvertex3f_vertexbuffer = NULL;
12681         rsurface.batchvertex3f_bufferoffset = 0;
12682         rsurface.batchsvector3f = NULL;
12683         rsurface.batchsvector3f_vertexbuffer = NULL;
12684         rsurface.batchsvector3f_bufferoffset = 0;
12685         rsurface.batchtvector3f = NULL;
12686         rsurface.batchtvector3f_vertexbuffer = NULL;
12687         rsurface.batchtvector3f_bufferoffset = 0;
12688         rsurface.batchnormal3f  = NULL;
12689         rsurface.batchnormal3f_vertexbuffer = NULL;
12690         rsurface.batchnormal3f_bufferoffset = 0;
12691         rsurface.batchlightmapcolor4f = NULL;
12692         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
12693         rsurface.batchlightmapcolor4f_bufferoffset = 0;
12694         rsurface.batchtexcoordtexture2f = NULL;
12695         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12696         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12697         rsurface.batchtexcoordlightmap2f = NULL;
12698         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
12699         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
12700         rsurface.batchvertexmesh = NULL;
12701         rsurface.batchvertexmeshbuffer = NULL;
12702         rsurface.batchvertex3fbuffer = NULL;
12703         rsurface.batchelement3i = NULL;
12704         rsurface.batchelement3i_indexbuffer = NULL;
12705         rsurface.batchelement3i_bufferoffset = 0;
12706         rsurface.batchelement3s = NULL;
12707         rsurface.batchelement3s_indexbuffer = NULL;
12708         rsurface.batchelement3s_bufferoffset = 0;
12709         rsurface.passcolor4f = NULL;
12710         rsurface.passcolor4f_vertexbuffer = NULL;
12711         rsurface.passcolor4f_bufferoffset = 0;
12712 }
12713
12714 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)
12715 {
12716         rsurface.entity = r_refdef.scene.worldentity;
12717         rsurface.skeleton = NULL;
12718         rsurface.ent_skinnum = 0;
12719         rsurface.ent_qwskin = -1;
12720         rsurface.ent_shadertime = shadertime;
12721         rsurface.ent_flags = entflags;
12722         rsurface.modelnumvertices = numvertices;
12723         rsurface.modelnumtriangles = numtriangles;
12724         rsurface.matrix = *matrix;
12725         rsurface.inversematrix = *inversematrix;
12726         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
12727         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
12728         R_EntityMatrix(&rsurface.matrix);
12729         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
12730         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
12731         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
12732         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
12733         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
12734         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
12735         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
12736         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
12737         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
12738         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
12739         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
12740         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
12741         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);
12742         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
12743         rsurface.frameblend[0].lerp = 1;
12744         rsurface.ent_alttextures = false;
12745         rsurface.basepolygonfactor = r_refdef.polygonfactor;
12746         rsurface.basepolygonoffset = r_refdef.polygonoffset;
12747         if (wanttangents)
12748         {
12749                 rsurface.modelvertex3f = (float *)vertex3f;
12750                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
12751                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
12752                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
12753         }
12754         else if (wantnormals)
12755         {
12756                 rsurface.modelvertex3f = (float *)vertex3f;
12757                 rsurface.modelsvector3f = NULL;
12758                 rsurface.modeltvector3f = NULL;
12759                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
12760         }
12761         else
12762         {
12763                 rsurface.modelvertex3f = (float *)vertex3f;
12764                 rsurface.modelsvector3f = NULL;
12765                 rsurface.modeltvector3f = NULL;
12766                 rsurface.modelnormal3f = NULL;
12767         }
12768         rsurface.modelvertexmesh = NULL;
12769         rsurface.modelvertexmeshbuffer = NULL;
12770         rsurface.modelvertex3fbuffer = NULL;
12771         rsurface.modelvertex3f_vertexbuffer = 0;
12772         rsurface.modelvertex3f_bufferoffset = 0;
12773         rsurface.modelsvector3f_vertexbuffer = 0;
12774         rsurface.modelsvector3f_bufferoffset = 0;
12775         rsurface.modeltvector3f_vertexbuffer = 0;
12776         rsurface.modeltvector3f_bufferoffset = 0;
12777         rsurface.modelnormal3f_vertexbuffer = 0;
12778         rsurface.modelnormal3f_bufferoffset = 0;
12779         rsurface.modelgeneratedvertex = true;
12780         rsurface.modellightmapcolor4f  = (float *)color4f;
12781         rsurface.modellightmapcolor4f_vertexbuffer = 0;
12782         rsurface.modellightmapcolor4f_bufferoffset = 0;
12783         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
12784         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
12785         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
12786         rsurface.modeltexcoordlightmap2f  = NULL;
12787         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
12788         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
12789         rsurface.modelelement3i = (int *)element3i;
12790         rsurface.modelelement3i_indexbuffer = NULL;
12791         rsurface.modelelement3i_bufferoffset = 0;
12792         rsurface.modelelement3s = (unsigned short *)element3s;
12793         rsurface.modelelement3s_indexbuffer = NULL;
12794         rsurface.modelelement3s_bufferoffset = 0;
12795         rsurface.modellightmapoffsets = NULL;
12796         rsurface.modelsurfaces = NULL;
12797         rsurface.batchgeneratedvertex = false;
12798         rsurface.batchfirstvertex = 0;
12799         rsurface.batchnumvertices = 0;
12800         rsurface.batchfirsttriangle = 0;
12801         rsurface.batchnumtriangles = 0;
12802         rsurface.batchvertex3f  = NULL;
12803         rsurface.batchvertex3f_vertexbuffer = NULL;
12804         rsurface.batchvertex3f_bufferoffset = 0;
12805         rsurface.batchsvector3f = NULL;
12806         rsurface.batchsvector3f_vertexbuffer = NULL;
12807         rsurface.batchsvector3f_bufferoffset = 0;
12808         rsurface.batchtvector3f = NULL;
12809         rsurface.batchtvector3f_vertexbuffer = NULL;
12810         rsurface.batchtvector3f_bufferoffset = 0;
12811         rsurface.batchnormal3f  = NULL;
12812         rsurface.batchnormal3f_vertexbuffer = NULL;
12813         rsurface.batchnormal3f_bufferoffset = 0;
12814         rsurface.batchlightmapcolor4f = NULL;
12815         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
12816         rsurface.batchlightmapcolor4f_bufferoffset = 0;
12817         rsurface.batchtexcoordtexture2f = NULL;
12818         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12819         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12820         rsurface.batchtexcoordlightmap2f = NULL;
12821         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
12822         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
12823         rsurface.batchvertexmesh = NULL;
12824         rsurface.batchvertexmeshbuffer = NULL;
12825         rsurface.batchvertex3fbuffer = NULL;
12826         rsurface.batchelement3i = NULL;
12827         rsurface.batchelement3i_indexbuffer = NULL;
12828         rsurface.batchelement3i_bufferoffset = 0;
12829         rsurface.batchelement3s = NULL;
12830         rsurface.batchelement3s_indexbuffer = NULL;
12831         rsurface.batchelement3s_bufferoffset = 0;
12832         rsurface.passcolor4f = NULL;
12833         rsurface.passcolor4f_vertexbuffer = NULL;
12834         rsurface.passcolor4f_bufferoffset = 0;
12835
12836         if (rsurface.modelnumvertices && rsurface.modelelement3i)
12837         {
12838                 if ((wantnormals || wanttangents) && !normal3f)
12839                 {
12840                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
12841                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
12842                 }
12843                 if (wanttangents && !svector3f)
12844                 {
12845                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
12846                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
12847                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
12848                 }
12849         }
12850 }
12851
12852 float RSurf_FogPoint(const float *v)
12853 {
12854         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
12855         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
12856         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
12857         float FogHeightFade = r_refdef.fogheightfade;
12858         float fogfrac;
12859         unsigned int fogmasktableindex;
12860         if (r_refdef.fogplaneviewabove)
12861                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
12862         else
12863                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
12864         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
12865         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
12866 }
12867
12868 float RSurf_FogVertex(const float *v)
12869 {
12870         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
12871         float FogPlaneViewDist = rsurface.fogplaneviewdist;
12872         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
12873         float FogHeightFade = rsurface.fogheightfade;
12874         float fogfrac;
12875         unsigned int fogmasktableindex;
12876         if (r_refdef.fogplaneviewabove)
12877                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
12878         else
12879                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
12880         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
12881         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
12882 }
12883
12884 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
12885 {
12886         int i;
12887         for (i = 0;i < numelements;i++)
12888                 outelement3i[i] = inelement3i[i] + adjust;
12889 }
12890
12891 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
12892 extern cvar_t gl_vbo;
12893 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
12894 {
12895         int deformindex;
12896         int firsttriangle;
12897         int numtriangles;
12898         int firstvertex;
12899         int endvertex;
12900         int numvertices;
12901         int surfacefirsttriangle;
12902         int surfacenumtriangles;
12903         int surfacefirstvertex;
12904         int surfaceendvertex;
12905         int surfacenumvertices;
12906         int batchnumvertices;
12907         int batchnumtriangles;
12908         int needsupdate;
12909         int i, j;
12910         qboolean gaps;
12911         qboolean dynamicvertex;
12912         float amplitude;
12913         float animpos;
12914         float scale;
12915         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
12916         float waveparms[4];
12917         q3shaderinfo_deform_t *deform;
12918         const msurface_t *surface, *firstsurface;
12919         r_vertexmesh_t *vertexmesh;
12920         if (!texturenumsurfaces)
12921                 return;
12922         // find vertex range of this surface batch
12923         gaps = false;
12924         firstsurface = texturesurfacelist[0];
12925         firsttriangle = firstsurface->num_firsttriangle;
12926         batchnumvertices = 0;
12927         batchnumtriangles = 0;
12928         firstvertex = endvertex = firstsurface->num_firstvertex;
12929         for (i = 0;i < texturenumsurfaces;i++)
12930         {
12931                 surface = texturesurfacelist[i];
12932                 if (surface != firstsurface + i)
12933                         gaps = true;
12934                 surfacefirstvertex = surface->num_firstvertex;
12935                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
12936                 surfacenumvertices = surface->num_vertices;
12937                 surfacenumtriangles = surface->num_triangles;
12938                 if (firstvertex > surfacefirstvertex)
12939                         firstvertex = surfacefirstvertex;
12940                 if (endvertex < surfaceendvertex)
12941                         endvertex = surfaceendvertex;
12942                 batchnumvertices += surfacenumvertices;
12943                 batchnumtriangles += surfacenumtriangles;
12944         }
12945
12946         // we now know the vertex range used, and if there are any gaps in it
12947         rsurface.batchfirstvertex = firstvertex;
12948         rsurface.batchnumvertices = endvertex - firstvertex;
12949         rsurface.batchfirsttriangle = firsttriangle;
12950         rsurface.batchnumtriangles = batchnumtriangles;
12951
12952         // this variable holds flags for which properties have been updated that
12953         // may require regenerating vertexmesh array...
12954         needsupdate = 0;
12955
12956         // check if any dynamic vertex processing must occur
12957         dynamicvertex = false;
12958
12959         // if there is a chance of animated vertex colors, it's a dynamic batch
12960         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
12961         {
12962                 dynamicvertex = true;
12963                 batchneed |= BATCHNEED_NOGAPS;
12964                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
12965         }
12966
12967         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
12968         {
12969                 switch (deform->deform)
12970                 {
12971                 default:
12972                 case Q3DEFORM_PROJECTIONSHADOW:
12973                 case Q3DEFORM_TEXT0:
12974                 case Q3DEFORM_TEXT1:
12975                 case Q3DEFORM_TEXT2:
12976                 case Q3DEFORM_TEXT3:
12977                 case Q3DEFORM_TEXT4:
12978                 case Q3DEFORM_TEXT5:
12979                 case Q3DEFORM_TEXT6:
12980                 case Q3DEFORM_TEXT7:
12981                 case Q3DEFORM_NONE:
12982                         break;
12983                 case Q3DEFORM_AUTOSPRITE:
12984                         dynamicvertex = true;
12985                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
12986                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
12987                         break;
12988                 case Q3DEFORM_AUTOSPRITE2:
12989                         dynamicvertex = true;
12990                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
12991                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
12992                         break;
12993                 case Q3DEFORM_NORMAL:
12994                         dynamicvertex = true;
12995                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
12996                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
12997                         break;
12998                 case Q3DEFORM_WAVE:
12999                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
13000                                 break; // if wavefunc is a nop, ignore this transform
13001                         dynamicvertex = true;
13002                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
13003                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
13004                         break;
13005                 case Q3DEFORM_BULGE:
13006                         dynamicvertex = true;
13007                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
13008                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
13009                         break;
13010                 case Q3DEFORM_MOVE:
13011                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
13012                                 break; // if wavefunc is a nop, ignore this transform
13013                         dynamicvertex = true;
13014                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
13015                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
13016                         break;
13017                 }
13018         }
13019         switch(rsurface.texture->tcgen.tcgen)
13020         {
13021         default:
13022         case Q3TCGEN_TEXTURE:
13023                 break;
13024         case Q3TCGEN_LIGHTMAP:
13025                 dynamicvertex = true;
13026                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
13027                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
13028                 break;
13029         case Q3TCGEN_VECTOR:
13030                 dynamicvertex = true;
13031                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
13032                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
13033                 break;
13034         case Q3TCGEN_ENVIRONMENT:
13035                 dynamicvertex = true;
13036                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
13037                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
13038                 break;
13039         }
13040         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
13041         {
13042                 dynamicvertex = true;
13043                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
13044                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
13045         }
13046
13047         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
13048         {
13049                 dynamicvertex = true;
13050                 batchneed |= BATCHNEED_NOGAPS;
13051                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
13052         }
13053
13054         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
13055         {
13056                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
13057                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
13058                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
13059                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
13060                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
13061                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
13062                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
13063         }
13064
13065         // when the model data has no vertex buffer (dynamic mesh), we need to
13066         // eliminate gaps
13067         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
13068                 batchneed |= BATCHNEED_NOGAPS;
13069
13070         // if needsupdate, we have to do a dynamic vertex batch for sure
13071         if (needsupdate & batchneed)
13072                 dynamicvertex = true;
13073
13074         // see if we need to build vertexmesh from arrays
13075         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
13076                 dynamicvertex = true;
13077
13078         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
13079         // also some drivers strongly dislike firstvertex
13080         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
13081                 dynamicvertex = true;
13082
13083         rsurface.batchvertex3f = rsurface.modelvertex3f;
13084         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
13085         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
13086         rsurface.batchsvector3f = rsurface.modelsvector3f;
13087         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
13088         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
13089         rsurface.batchtvector3f = rsurface.modeltvector3f;
13090         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
13091         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
13092         rsurface.batchnormal3f = rsurface.modelnormal3f;
13093         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
13094         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
13095         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
13096         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
13097         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
13098         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
13099         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
13100         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
13101         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
13102         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
13103         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
13104         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
13105         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
13106         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
13107         rsurface.batchelement3i = rsurface.modelelement3i;
13108         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
13109         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
13110         rsurface.batchelement3s = rsurface.modelelement3s;
13111         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
13112         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
13113
13114         // if any dynamic vertex processing has to occur in software, we copy the
13115         // entire surface list together before processing to rebase the vertices
13116         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
13117         //
13118         // if any gaps exist and we do not have a static vertex buffer, we have to
13119         // copy the surface list together to avoid wasting upload bandwidth on the
13120         // vertices in the gaps.
13121         //
13122         // if gaps exist and we have a static vertex buffer, we still have to
13123         // combine the index buffer ranges into one dynamic index buffer.
13124         //
13125         // in all cases we end up with data that can be drawn in one call.
13126
13127         if (!dynamicvertex)
13128         {
13129                 // static vertex data, just set pointers...
13130                 rsurface.batchgeneratedvertex = false;
13131                 // if there are gaps, we want to build a combined index buffer,
13132                 // otherwise use the original static buffer with an appropriate offset
13133                 if (gaps)
13134                 {
13135                         // build a new triangle elements array for this batch
13136                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
13137                         rsurface.batchfirsttriangle = 0;
13138                         numtriangles = 0;
13139                         for (i = 0;i < texturenumsurfaces;i++)
13140                         {
13141                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
13142                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
13143                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
13144                                 numtriangles += surfacenumtriangles;
13145                         }
13146                         rsurface.batchelement3i_indexbuffer = NULL;
13147                         rsurface.batchelement3i_bufferoffset = 0;
13148                         rsurface.batchelement3s = NULL;
13149                         rsurface.batchelement3s_indexbuffer = NULL;
13150                         rsurface.batchelement3s_bufferoffset = 0;
13151                         if (endvertex <= 65536)
13152                         {
13153                                 // make a 16bit (unsigned short) index array if possible
13154                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
13155                                 for (i = 0;i < numtriangles*3;i++)
13156                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
13157                         }
13158                 }
13159                 return;
13160         }
13161
13162         // something needs software processing, do it for real...
13163         // we only directly handle separate array data in this case and then
13164         // generate interleaved data if needed...
13165         rsurface.batchgeneratedvertex = true;
13166
13167         // now copy the vertex data into a combined array and make an index array
13168         // (this is what Quake3 does all the time)
13169         //if (gaps || rsurface.batchfirstvertex)
13170         {
13171                 rsurface.batchvertex3fbuffer = NULL;
13172                 rsurface.batchvertexmesh = NULL;
13173                 rsurface.batchvertexmeshbuffer = NULL;
13174                 rsurface.batchvertex3f = NULL;
13175                 rsurface.batchvertex3f_vertexbuffer = NULL;
13176                 rsurface.batchvertex3f_bufferoffset = 0;
13177                 rsurface.batchsvector3f = NULL;
13178                 rsurface.batchsvector3f_vertexbuffer = NULL;
13179                 rsurface.batchsvector3f_bufferoffset = 0;
13180                 rsurface.batchtvector3f = NULL;
13181                 rsurface.batchtvector3f_vertexbuffer = NULL;
13182                 rsurface.batchtvector3f_bufferoffset = 0;
13183                 rsurface.batchnormal3f = NULL;
13184                 rsurface.batchnormal3f_vertexbuffer = NULL;
13185                 rsurface.batchnormal3f_bufferoffset = 0;
13186                 rsurface.batchlightmapcolor4f = NULL;
13187                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
13188                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
13189                 rsurface.batchtexcoordtexture2f = NULL;
13190                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
13191                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
13192                 rsurface.batchtexcoordlightmap2f = NULL;
13193                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
13194                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
13195                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
13196                 rsurface.batchelement3i_indexbuffer = NULL;
13197                 rsurface.batchelement3i_bufferoffset = 0;
13198                 rsurface.batchelement3s = NULL;
13199                 rsurface.batchelement3s_indexbuffer = NULL;
13200                 rsurface.batchelement3s_bufferoffset = 0;
13201                 // we'll only be setting up certain arrays as needed
13202                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
13203                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
13204                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
13205                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13206                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
13207                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13208                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
13209                 {
13210                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13211                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13212                 }
13213                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
13214                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
13215                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
13216                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
13217                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
13218                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
13219                 numvertices = 0;
13220                 numtriangles = 0;
13221                 for (i = 0;i < texturenumsurfaces;i++)
13222                 {
13223                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
13224                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
13225                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
13226                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
13227                         // copy only the data requested
13228                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
13229                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
13230                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
13231                         {
13232                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
13233                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
13234                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
13235                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
13236                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
13237                                 {
13238                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
13239                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
13240                                 }
13241                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
13242                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
13243                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
13244                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
13245                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
13246                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
13247                         }
13248                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
13249                         numvertices += surfacenumvertices;
13250                         numtriangles += surfacenumtriangles;
13251                 }
13252
13253                 // generate a 16bit index array as well if possible
13254                 // (in general, dynamic batches fit)
13255                 if (numvertices <= 65536)
13256                 {
13257                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
13258                         for (i = 0;i < numtriangles*3;i++)
13259                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
13260                 }
13261
13262                 // since we've copied everything, the batch now starts at 0
13263                 rsurface.batchfirstvertex = 0;
13264                 rsurface.batchnumvertices = batchnumvertices;
13265                 rsurface.batchfirsttriangle = 0;
13266                 rsurface.batchnumtriangles = batchnumtriangles;
13267         }
13268
13269         // q1bsp surfaces rendered in vertex color mode have to have colors
13270         // calculated based on lightstyles
13271         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
13272         {
13273                 // generate color arrays for the surfaces in this list
13274                 int c[4];
13275                 int scale;
13276                 int size3;
13277                 const int *offsets;
13278                 const unsigned char *lm;
13279                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
13280                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
13281                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
13282                 numvertices = 0;
13283                 for (i = 0;i < texturenumsurfaces;i++)
13284                 {
13285                         surface = texturesurfacelist[i];
13286                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
13287                         surfacenumvertices = surface->num_vertices;
13288                         if (surface->lightmapinfo->samples)
13289                         {
13290                                 for (j = 0;j < surfacenumvertices;j++)
13291                                 {
13292                                         lm = surface->lightmapinfo->samples + offsets[j];
13293                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
13294                                         VectorScale(lm, scale, c);
13295                                         if (surface->lightmapinfo->styles[1] != 255)
13296                                         {
13297                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
13298                                                 lm += size3;
13299                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
13300                                                 VectorMA(c, scale, lm, c);
13301                                                 if (surface->lightmapinfo->styles[2] != 255)
13302                                                 {
13303                                                         lm += size3;
13304                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
13305                                                         VectorMA(c, scale, lm, c);
13306                                                         if (surface->lightmapinfo->styles[3] != 255)
13307                                                         {
13308                                                                 lm += size3;
13309                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
13310                                                                 VectorMA(c, scale, lm, c);
13311                                                         }
13312                                                 }
13313                                         }
13314                                         c[0] >>= 7;
13315                                         c[1] >>= 7;
13316                                         c[2] >>= 7;
13317                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, min(c[0], 255) * (1.0f / 255.0f), min(c[1], 255) * (1.0f / 255.0f), min(c[2], 255) * (1.0f / 255.0f), 1);
13318                                         numvertices++;
13319                                 }
13320                         }
13321                         else
13322                         {
13323                                 for (j = 0;j < surfacenumvertices;j++)
13324                                 {
13325                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
13326                                         numvertices++;
13327                                 }
13328                         }
13329                 }
13330         }
13331
13332         // if vertices are deformed (sprite flares and things in maps, possibly
13333         // water waves, bulges and other deformations), modify the copied vertices
13334         // in place
13335         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
13336         {
13337                 switch (deform->deform)
13338                 {
13339                 default:
13340                 case Q3DEFORM_PROJECTIONSHADOW:
13341                 case Q3DEFORM_TEXT0:
13342                 case Q3DEFORM_TEXT1:
13343                 case Q3DEFORM_TEXT2:
13344                 case Q3DEFORM_TEXT3:
13345                 case Q3DEFORM_TEXT4:
13346                 case Q3DEFORM_TEXT5:
13347                 case Q3DEFORM_TEXT6:
13348                 case Q3DEFORM_TEXT7:
13349                 case Q3DEFORM_NONE:
13350                         break;
13351                 case Q3DEFORM_AUTOSPRITE:
13352                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
13353                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
13354                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
13355                         VectorNormalize(newforward);
13356                         VectorNormalize(newright);
13357                         VectorNormalize(newup);
13358 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
13359 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
13360 //                      rsurface.batchvertex3f_bufferoffset = 0;
13361 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
13362 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
13363 //                      rsurface.batchsvector3f_bufferoffset = 0;
13364 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
13365 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
13366 //                      rsurface.batchtvector3f_bufferoffset = 0;
13367 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
13368 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
13369 //                      rsurface.batchnormal3f_bufferoffset = 0;
13370                         // a single autosprite surface can contain multiple sprites...
13371                         for (j = 0;j < batchnumvertices - 3;j += 4)
13372                         {
13373                                 VectorClear(center);
13374                                 for (i = 0;i < 4;i++)
13375                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
13376                                 VectorScale(center, 0.25f, center);
13377                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
13378                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
13379                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
13380                                 for (i = 0;i < 4;i++)
13381                                 {
13382                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
13383                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
13384                                 }
13385                         }
13386                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
13387                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
13388                         Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
13389                         break;
13390                 case Q3DEFORM_AUTOSPRITE2:
13391                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
13392                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
13393                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
13394                         VectorNormalize(newforward);
13395                         VectorNormalize(newright);
13396                         VectorNormalize(newup);
13397 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
13398 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
13399 //                      rsurface.batchvertex3f_bufferoffset = 0;
13400                         {
13401                                 const float *v1, *v2;
13402                                 vec3_t start, end;
13403                                 float f, l;
13404                                 struct
13405                                 {
13406                                         float length2;
13407                                         const float *v1;
13408                                         const float *v2;
13409                                 }
13410                                 shortest[2];
13411                                 memset(shortest, 0, sizeof(shortest));
13412                                 // a single autosprite surface can contain multiple sprites...
13413                                 for (j = 0;j < batchnumvertices - 3;j += 4)
13414                                 {
13415                                         VectorClear(center);
13416                                         for (i = 0;i < 4;i++)
13417                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
13418                                         VectorScale(center, 0.25f, center);
13419                                         // find the two shortest edges, then use them to define the
13420                                         // axis vectors for rotating around the central axis
13421                                         for (i = 0;i < 6;i++)
13422                                         {
13423                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
13424                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
13425                                                 l = VectorDistance2(v1, v2);
13426                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
13427                                                 if (v1[2] != v2[2])
13428                                                         l += (1.0f / 1024.0f);
13429                                                 if (shortest[0].length2 > l || i == 0)
13430                                                 {
13431                                                         shortest[1] = shortest[0];
13432                                                         shortest[0].length2 = l;
13433                                                         shortest[0].v1 = v1;
13434                                                         shortest[0].v2 = v2;
13435                                                 }
13436                                                 else if (shortest[1].length2 > l || i == 1)
13437                                                 {
13438                                                         shortest[1].length2 = l;
13439                                                         shortest[1].v1 = v1;
13440                                                         shortest[1].v2 = v2;
13441                                                 }
13442                                         }
13443                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
13444                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
13445                                         // this calculates the right vector from the shortest edge
13446                                         // and the up vector from the edge midpoints
13447                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
13448                                         VectorNormalize(right);
13449                                         VectorSubtract(end, start, up);
13450                                         VectorNormalize(up);
13451                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
13452                                         VectorSubtract(rsurface.localvieworigin, center, forward);
13453                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
13454                                         VectorNegate(forward, forward);
13455                                         VectorReflect(forward, 0, up, forward);
13456                                         VectorNormalize(forward);
13457                                         CrossProduct(up, forward, newright);
13458                                         VectorNormalize(newright);
13459                                         // rotate the quad around the up axis vector, this is made
13460                                         // especially easy by the fact we know the quad is flat,
13461                                         // so we only have to subtract the center position and
13462                                         // measure distance along the right vector, and then
13463                                         // multiply that by the newright vector and add back the
13464                                         // center position
13465                                         // we also need to subtract the old position to undo the
13466                                         // displacement from the center, which we do with a
13467                                         // DotProduct, the subtraction/addition of center is also
13468                                         // optimized into DotProducts here
13469                                         l = DotProduct(right, center);
13470                                         for (i = 0;i < 4;i++)
13471                                         {
13472                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
13473                                                 f = DotProduct(right, v1) - l;
13474                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
13475                                         }
13476                                 }
13477                         }
13478                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
13479                         {
13480 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13481 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
13482 //                              rsurface.batchnormal3f_bufferoffset = 0;
13483                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
13484                         }
13485                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
13486                         {
13487 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13488 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
13489 //                              rsurface.batchsvector3f_bufferoffset = 0;
13490 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13491 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
13492 //                              rsurface.batchtvector3f_bufferoffset = 0;
13493                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
13494                         }
13495                         break;
13496                 case Q3DEFORM_NORMAL:
13497                         // deform the normals to make reflections wavey
13498                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
13499                         rsurface.batchnormal3f_vertexbuffer = NULL;
13500                         rsurface.batchnormal3f_bufferoffset = 0;
13501                         for (j = 0;j < batchnumvertices;j++)
13502                         {
13503                                 float vertex[3];
13504                                 float *normal = rsurface.batchnormal3f + 3*j;
13505                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
13506                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
13507                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
13508                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
13509                                 VectorNormalize(normal);
13510                         }
13511                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
13512                         {
13513 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13514 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
13515 //                              rsurface.batchsvector3f_bufferoffset = 0;
13516 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13517 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
13518 //                              rsurface.batchtvector3f_bufferoffset = 0;
13519                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
13520                         }
13521                         break;
13522                 case Q3DEFORM_WAVE:
13523                         // deform vertex array to make wavey water and flags and such
13524                         waveparms[0] = deform->waveparms[0];
13525                         waveparms[1] = deform->waveparms[1];
13526                         waveparms[2] = deform->waveparms[2];
13527                         waveparms[3] = deform->waveparms[3];
13528                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
13529                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
13530                         // this is how a divisor of vertex influence on deformation
13531                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
13532                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
13533 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
13534 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
13535 //                      rsurface.batchvertex3f_bufferoffset = 0;
13536 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
13537 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
13538 //                      rsurface.batchnormal3f_bufferoffset = 0;
13539                         for (j = 0;j < batchnumvertices;j++)
13540                         {
13541                                 // if the wavefunc depends on time, evaluate it per-vertex
13542                                 if (waveparms[3])
13543                                 {
13544                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
13545                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
13546                                 }
13547                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
13548                         }
13549                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
13550                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
13551                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
13552                         {
13553 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13554 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
13555 //                              rsurface.batchsvector3f_bufferoffset = 0;
13556 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13557 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
13558 //                              rsurface.batchtvector3f_bufferoffset = 0;
13559                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
13560                         }
13561                         break;
13562                 case Q3DEFORM_BULGE:
13563                         // deform vertex array to make the surface have moving bulges
13564 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
13565 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
13566 //                      rsurface.batchvertex3f_bufferoffset = 0;
13567 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
13568 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
13569 //                      rsurface.batchnormal3f_bufferoffset = 0;
13570                         for (j = 0;j < batchnumvertices;j++)
13571                         {
13572                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
13573                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
13574                         }
13575                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
13576                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
13577                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
13578                         {
13579 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13580 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
13581 //                              rsurface.batchsvector3f_bufferoffset = 0;
13582 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13583 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
13584 //                              rsurface.batchtvector3f_bufferoffset = 0;
13585                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
13586                         }
13587                         break;
13588                 case Q3DEFORM_MOVE:
13589                         // deform vertex array
13590                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
13591                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
13592                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
13593                         VectorScale(deform->parms, scale, waveparms);
13594 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
13595 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
13596 //                      rsurface.batchvertex3f_bufferoffset = 0;
13597                         for (j = 0;j < batchnumvertices;j++)
13598                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
13599                         break;
13600                 }
13601         }
13602
13603         // generate texcoords based on the chosen texcoord source
13604         switch(rsurface.texture->tcgen.tcgen)
13605         {
13606         default:
13607         case Q3TCGEN_TEXTURE:
13608                 break;
13609         case Q3TCGEN_LIGHTMAP:
13610 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
13611 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
13612 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
13613                 if (rsurface.batchtexcoordlightmap2f)
13614                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
13615                 break;
13616         case Q3TCGEN_VECTOR:
13617 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
13618 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
13619 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
13620                 for (j = 0;j < batchnumvertices;j++)
13621                 {
13622                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
13623                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
13624                 }
13625                 break;
13626         case Q3TCGEN_ENVIRONMENT:
13627                 // make environment reflections using a spheremap
13628                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
13629                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
13630                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
13631                 for (j = 0;j < batchnumvertices;j++)
13632                 {
13633                         // identical to Q3A's method, but executed in worldspace so
13634                         // carried models can be shiny too
13635
13636                         float viewer[3], d, reflected[3], worldreflected[3];
13637
13638                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
13639                         // VectorNormalize(viewer);
13640
13641                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
13642
13643                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
13644                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
13645                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
13646                         // note: this is proportinal to viewer, so we can normalize later
13647
13648                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
13649                         VectorNormalize(worldreflected);
13650
13651                         // note: this sphere map only uses world x and z!
13652                         // so positive and negative y will LOOK THE SAME.
13653                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
13654                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
13655                 }
13656                 break;
13657         }
13658         // the only tcmod that needs software vertex processing is turbulent, so
13659         // check for it here and apply the changes if needed
13660         // and we only support that as the first one
13661         // (handling a mixture of turbulent and other tcmods would be problematic
13662         //  without punting it entirely to a software path)
13663         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
13664         {
13665                 amplitude = rsurface.texture->tcmods[0].parms[1];
13666                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
13667 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
13668 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
13669 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
13670                 for (j = 0;j < batchnumvertices;j++)
13671                 {
13672                         rsurface.batchtexcoordtexture2f[j*2+0] += amplitude * sin(((rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
13673                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
13674                 }
13675         }
13676
13677         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
13678         {
13679                 // convert the modified arrays to vertex structs
13680 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
13681 //              rsurface.batchvertexmeshbuffer = NULL;
13682                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
13683                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
13684                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
13685                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
13686                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
13687                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
13688                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
13689                 {
13690                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
13691                         {
13692                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
13693                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
13694                         }
13695                 }
13696                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
13697                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
13698                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
13699                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
13700                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
13701                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
13702                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
13703                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
13704                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
13705         }
13706 }
13707
13708 void RSurf_DrawBatch(void)
13709 {
13710         // sometimes a zero triangle surface (usually a degenerate patch) makes it
13711         // through the pipeline, killing it earlier in the pipeline would have
13712         // per-surface overhead rather than per-batch overhead, so it's best to
13713         // reject it here, before it hits glDraw.
13714         if (rsurface.batchnumtriangles == 0)
13715                 return;
13716 #if 0
13717         // batch debugging code
13718         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
13719         {
13720                 int i;
13721                 int j;
13722                 int c;
13723                 const int *e;
13724                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
13725                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
13726                 {
13727                         c = e[i];
13728                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
13729                         {
13730                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
13731                                 {
13732                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
13733                                                 Sys_Error("RSurf_DrawBatch: index %i uses different texture (%s) than surface %i which it belongs to (which uses %s)\n", c, rsurface.texture->name, j, rsurface.modelsurfaces[j].texture->name);
13734                                         break;
13735                                 }
13736                         }
13737                 }
13738         }
13739 #endif
13740         R_Mesh_Draw(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchfirsttriangle, rsurface.batchnumtriangles, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
13741 }
13742
13743 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
13744 {
13745         // pick the closest matching water plane
13746         int planeindex, vertexindex, bestplaneindex = -1;
13747         float d, bestd;
13748         vec3_t vert;
13749         const float *v;
13750         r_waterstate_waterplane_t *p;
13751         qboolean prepared = false;
13752         bestd = 0;
13753         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
13754         {
13755                 if(p->camera_entity != rsurface.texture->camera_entity)
13756                         continue;
13757                 d = 0;
13758                 if(!prepared)
13759                 {
13760                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
13761                         prepared = true;
13762                         if(rsurface.batchnumvertices == 0)
13763                                 break;
13764                 }
13765                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
13766                 {
13767                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
13768                         d += fabs(PlaneDiff(vert, &p->plane));
13769                 }
13770                 if (bestd > d || bestplaneindex < 0)
13771                 {
13772                         bestd = d;
13773                         bestplaneindex = planeindex;
13774                 }
13775         }
13776         return bestplaneindex;
13777         // NOTE: this MAY return a totally unrelated water plane; we can ignore
13778         // this situation though, as it might be better to render single larger
13779         // batches with useless stuff (backface culled for example) than to
13780         // render multiple smaller batches
13781 }
13782
13783 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
13784 {
13785         int i;
13786         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
13787         rsurface.passcolor4f_vertexbuffer = 0;
13788         rsurface.passcolor4f_bufferoffset = 0;
13789         for (i = 0;i < rsurface.batchnumvertices;i++)
13790                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
13791 }
13792
13793 static void RSurf_DrawBatch_GL11_ApplyFog(void)
13794 {
13795         int i;
13796         float f;
13797         const float *v;
13798         const float *c;
13799         float *c2;
13800         if (rsurface.passcolor4f)
13801         {
13802                 // generate color arrays
13803                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
13804                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
13805                 rsurface.passcolor4f_vertexbuffer = 0;
13806                 rsurface.passcolor4f_bufferoffset = 0;
13807                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
13808                 {
13809                         f = RSurf_FogVertex(v);
13810                         c2[0] = c[0] * f;
13811                         c2[1] = c[1] * f;
13812                         c2[2] = c[2] * f;
13813                         c2[3] = c[3];
13814                 }
13815         }
13816         else
13817         {
13818                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
13819                 rsurface.passcolor4f_vertexbuffer = 0;
13820                 rsurface.passcolor4f_bufferoffset = 0;
13821                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
13822                 {
13823                         f = RSurf_FogVertex(v);
13824                         c2[0] = f;
13825                         c2[1] = f;
13826                         c2[2] = f;
13827                         c2[3] = 1;
13828                 }
13829         }
13830 }
13831
13832 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
13833 {
13834         int i;
13835         float f;
13836         const float *v;
13837         const float *c;
13838         float *c2;
13839         if (!rsurface.passcolor4f)
13840                 return;
13841         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
13842         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
13843         rsurface.passcolor4f_vertexbuffer = 0;
13844         rsurface.passcolor4f_bufferoffset = 0;
13845         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
13846         {
13847                 f = RSurf_FogVertex(v);
13848                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
13849                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
13850                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
13851                 c2[3] = c[3];
13852         }
13853 }
13854
13855 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
13856 {
13857         int i;
13858         const float *c;
13859         float *c2;
13860         if (!rsurface.passcolor4f)
13861                 return;
13862         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
13863         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
13864         rsurface.passcolor4f_vertexbuffer = 0;
13865         rsurface.passcolor4f_bufferoffset = 0;
13866         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
13867         {
13868                 c2[0] = c[0] * r;
13869                 c2[1] = c[1] * g;
13870                 c2[2] = c[2] * b;
13871                 c2[3] = c[3] * a;
13872         }
13873 }
13874
13875 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
13876 {
13877         int i;
13878         const float *c;
13879         float *c2;
13880         if (!rsurface.passcolor4f)
13881                 return;
13882         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
13883         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
13884         rsurface.passcolor4f_vertexbuffer = 0;
13885         rsurface.passcolor4f_bufferoffset = 0;
13886         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
13887         {
13888                 c2[0] = c[0] + r_refdef.scene.ambient;
13889                 c2[1] = c[1] + r_refdef.scene.ambient;
13890                 c2[2] = c[2] + r_refdef.scene.ambient;
13891                 c2[3] = c[3];
13892         }
13893 }
13894
13895 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
13896 {
13897         // TODO: optimize
13898         rsurface.passcolor4f = NULL;
13899         rsurface.passcolor4f_vertexbuffer = 0;
13900         rsurface.passcolor4f_bufferoffset = 0;
13901         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
13902         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
13903         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
13904         GL_Color(r, g, b, a);
13905         R_Mesh_TexBind(0, rsurface.lightmaptexture);
13906         RSurf_DrawBatch();
13907 }
13908
13909 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
13910 {
13911         // TODO: optimize applyfog && applycolor case
13912         // just apply fog if necessary, and tint the fog color array if necessary
13913         rsurface.passcolor4f = NULL;
13914         rsurface.passcolor4f_vertexbuffer = 0;
13915         rsurface.passcolor4f_bufferoffset = 0;
13916         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
13917         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
13918         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
13919         GL_Color(r, g, b, a);
13920         RSurf_DrawBatch();
13921 }
13922
13923 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
13924 {
13925         // TODO: optimize
13926         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
13927         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
13928         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
13929         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
13930         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
13931         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
13932         GL_Color(r, g, b, a);
13933         RSurf_DrawBatch();
13934 }
13935
13936 static void RSurf_DrawBatch_GL11_ClampColor(void)
13937 {
13938         int i;
13939         const float *c1;
13940         float *c2;
13941         if (!rsurface.passcolor4f)
13942                 return;
13943         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
13944         {
13945                 c2[0] = bound(0.0f, c1[0], 1.0f);
13946                 c2[1] = bound(0.0f, c1[1], 1.0f);
13947                 c2[2] = bound(0.0f, c1[2], 1.0f);
13948                 c2[3] = bound(0.0f, c1[3], 1.0f);
13949         }
13950 }
13951
13952 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
13953 {
13954         int i;
13955         float f;
13956         const float *v;
13957         const float *n;
13958         float *c;
13959         //vec3_t eyedir;
13960
13961         // fake shading
13962         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
13963         rsurface.passcolor4f_vertexbuffer = 0;
13964         rsurface.passcolor4f_bufferoffset = 0;
13965         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
13966         {
13967                 f = -DotProduct(r_refdef.view.forward, n);
13968                 f = max(0, f);
13969                 f = f * 0.85 + 0.15; // work around so stuff won't get black
13970                 f *= r_refdef.lightmapintensity;
13971                 Vector4Set(c, f, f, f, 1);
13972         }
13973 }
13974
13975 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
13976 {
13977         RSurf_DrawBatch_GL11_ApplyFakeLight();
13978         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
13979         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
13980         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
13981         GL_Color(r, g, b, a);
13982         RSurf_DrawBatch();
13983 }
13984
13985 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
13986 {
13987         int i;
13988         float f;
13989         float alpha;
13990         const float *v;
13991         const float *n;
13992         float *c;
13993         vec3_t ambientcolor;
13994         vec3_t diffusecolor;
13995         vec3_t lightdir;
13996         // TODO: optimize
13997         // model lighting
13998         VectorCopy(rsurface.modellight_lightdir, lightdir);
13999         f = 0.5f * r_refdef.lightmapintensity;
14000         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
14001         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
14002         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
14003         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
14004         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
14005         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
14006         alpha = *a;
14007         if (VectorLength2(diffusecolor) > 0)
14008         {
14009                 // q3-style directional shading
14010                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
14011                 rsurface.passcolor4f_vertexbuffer = 0;
14012                 rsurface.passcolor4f_bufferoffset = 0;
14013                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
14014                 {
14015                         if ((f = DotProduct(n, lightdir)) > 0)
14016                                 VectorMA(ambientcolor, f, diffusecolor, c);
14017                         else
14018                                 VectorCopy(ambientcolor, c);
14019                         c[3] = alpha;
14020                 }
14021                 *r = 1;
14022                 *g = 1;
14023                 *b = 1;
14024                 *a = 1;
14025                 *applycolor = false;
14026         }
14027         else
14028         {
14029                 *r = ambientcolor[0];
14030                 *g = ambientcolor[1];
14031                 *b = ambientcolor[2];
14032                 rsurface.passcolor4f = NULL;
14033                 rsurface.passcolor4f_vertexbuffer = 0;
14034                 rsurface.passcolor4f_bufferoffset = 0;
14035         }
14036 }
14037
14038 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
14039 {
14040         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
14041         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
14042         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
14043         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
14044         GL_Color(r, g, b, a);
14045         RSurf_DrawBatch();
14046 }
14047
14048 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
14049 {
14050         int i;
14051         float f;
14052         const float *v;
14053         float *c;
14054         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
14055         {
14056                 f = 1 - RSurf_FogVertex(v);
14057                 c[0] = r;
14058                 c[1] = g;
14059                 c[2] = b;
14060                 c[3] = f * a;
14061         }
14062 }
14063
14064 void RSurf_SetupDepthAndCulling(void)
14065 {
14066         // submodels are biased to avoid z-fighting with world surfaces that they
14067         // may be exactly overlapping (avoids z-fighting artifacts on certain
14068         // doors and things in Quake maps)
14069         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
14070         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
14071         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
14072         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
14073 }
14074
14075 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
14076 {
14077         // transparent sky would be ridiculous
14078         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
14079                 return;
14080         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14081         skyrenderlater = true;
14082         RSurf_SetupDepthAndCulling();
14083         GL_DepthMask(true);
14084         // LordHavoc: HalfLife maps have freaky skypolys so don't use
14085         // skymasking on them, and Quake3 never did sky masking (unlike
14086         // software Quake and software Quake2), so disable the sky masking
14087         // in Quake3 maps as it causes problems with q3map2 sky tricks,
14088         // and skymasking also looks very bad when noclipping outside the
14089         // level, so don't use it then either.
14090         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
14091         {
14092                 R_Mesh_ResetTextureState();
14093                 if (skyrendermasked)
14094                 {
14095                         R_SetupShader_DepthOrShadow();
14096                         // depth-only (masking)
14097                         GL_ColorMask(0,0,0,0);
14098                         // just to make sure that braindead drivers don't draw
14099                         // anything despite that colormask...
14100                         GL_BlendFunc(GL_ZERO, GL_ONE);
14101                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
14102                         if (rsurface.batchvertex3fbuffer)
14103                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
14104                         else
14105                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
14106                 }
14107                 else
14108                 {
14109                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14110                         // fog sky
14111                         GL_BlendFunc(GL_ONE, GL_ZERO);
14112                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
14113                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
14114                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14115                 }
14116                 RSurf_DrawBatch();
14117                 if (skyrendermasked)
14118                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
14119         }
14120         R_Mesh_ResetTextureState();
14121         GL_Color(1, 1, 1, 1);
14122 }
14123
14124 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
14125 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
14126 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
14127 {
14128         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
14129                 return;
14130         if (prepass)
14131         {
14132                 // render screenspace normalmap to texture
14133                 GL_DepthMask(true);
14134                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
14135                 RSurf_DrawBatch();
14136                 return;
14137         }
14138
14139         // bind lightmap texture
14140
14141         // water/refraction/reflection/camera surfaces have to be handled specially
14142         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
14143         {
14144                 int start, end, startplaneindex;
14145                 for (start = 0;start < texturenumsurfaces;start = end)
14146                 {
14147                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
14148                         if(startplaneindex < 0)
14149                         {
14150                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
14151                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
14152                                 end = start + 1;
14153                                 continue;
14154                         }
14155                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
14156                                 ;
14157                         // now that we have a batch using the same planeindex, render it
14158                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
14159                         {
14160                                 // render water or distortion background
14161                                 GL_DepthMask(true);
14162                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex));
14163                                 RSurf_DrawBatch();
14164                                 // blend surface on top
14165                                 GL_DepthMask(false);
14166                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
14167                                 RSurf_DrawBatch();
14168                         }
14169                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
14170                         {
14171                                 // render surface with reflection texture as input
14172                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
14173                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex));
14174                                 RSurf_DrawBatch();
14175                         }
14176                 }
14177                 return;
14178         }
14179
14180         // render surface batch normally
14181         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
14182         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
14183         RSurf_DrawBatch();
14184 }
14185
14186 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
14187 {
14188         // OpenGL 1.3 path - anything not completely ancient
14189         qboolean applycolor;
14190         qboolean applyfog;
14191         int layerindex;
14192         const texturelayer_t *layer;
14193         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
14194         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
14195
14196         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
14197         {
14198                 vec4_t layercolor;
14199                 int layertexrgbscale;
14200                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
14201                 {
14202                         if (layerindex == 0)
14203                                 GL_AlphaTest(true);
14204                         else
14205                         {
14206                                 GL_AlphaTest(false);
14207                                 GL_DepthFunc(GL_EQUAL);
14208                         }
14209                 }
14210                 GL_DepthMask(layer->depthmask && writedepth);
14211                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
14212                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
14213                 {
14214                         layertexrgbscale = 4;
14215                         VectorScale(layer->color, 0.25f, layercolor);
14216                 }
14217                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
14218                 {
14219                         layertexrgbscale = 2;
14220                         VectorScale(layer->color, 0.5f, layercolor);
14221                 }
14222                 else
14223                 {
14224                         layertexrgbscale = 1;
14225                         VectorScale(layer->color, 1.0f, layercolor);
14226                 }
14227                 layercolor[3] = layer->color[3];
14228                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
14229                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
14230                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
14231                 switch (layer->type)
14232                 {
14233                 case TEXTURELAYERTYPE_LITTEXTURE:
14234                         // single-pass lightmapped texture with 2x rgbscale
14235                         R_Mesh_TexBind(0, r_texture_white);
14236                         R_Mesh_TexMatrix(0, NULL);
14237                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
14238                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
14239                         R_Mesh_TexBind(1, layer->texture);
14240                         R_Mesh_TexMatrix(1, &layer->texmatrix);
14241                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
14242                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
14243                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
14244                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
14245                         else if (FAKELIGHT_ENABLED)
14246                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
14247                         else if (rsurface.uselightmaptexture)
14248                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
14249                         else
14250                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
14251                         break;
14252                 case TEXTURELAYERTYPE_TEXTURE:
14253                         // singletexture unlit texture with transparency support
14254                         R_Mesh_TexBind(0, layer->texture);
14255                         R_Mesh_TexMatrix(0, &layer->texmatrix);
14256                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
14257                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
14258                         R_Mesh_TexBind(1, 0);
14259                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
14260                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
14261                         break;
14262                 case TEXTURELAYERTYPE_FOG:
14263                         // singletexture fogging
14264                         if (layer->texture)
14265                         {
14266                                 R_Mesh_TexBind(0, layer->texture);
14267                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
14268                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
14269                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
14270                         }
14271                         else
14272                         {
14273                                 R_Mesh_TexBind(0, 0);
14274                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
14275                         }
14276                         R_Mesh_TexBind(1, 0);
14277                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
14278                         // generate a color array for the fog pass
14279                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
14280                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
14281                         RSurf_DrawBatch();
14282                         break;
14283                 default:
14284                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
14285                 }
14286         }
14287         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
14288         {
14289                 GL_DepthFunc(GL_LEQUAL);
14290                 GL_AlphaTest(false);
14291         }
14292 }
14293
14294 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
14295 {
14296         // OpenGL 1.1 - crusty old voodoo path
14297         qboolean applyfog;
14298         int layerindex;
14299         const texturelayer_t *layer;
14300         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
14301         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
14302
14303         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
14304         {
14305                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
14306                 {
14307                         if (layerindex == 0)
14308                                 GL_AlphaTest(true);
14309                         else
14310                         {
14311                                 GL_AlphaTest(false);
14312                                 GL_DepthFunc(GL_EQUAL);
14313                         }
14314                 }
14315                 GL_DepthMask(layer->depthmask && writedepth);
14316                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
14317                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
14318                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
14319                 switch (layer->type)
14320                 {
14321                 case TEXTURELAYERTYPE_LITTEXTURE:
14322                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
14323                         {
14324                                 // two-pass lit texture with 2x rgbscale
14325                                 // first the lightmap pass
14326                                 R_Mesh_TexBind(0, r_texture_white);
14327                                 R_Mesh_TexMatrix(0, NULL);
14328                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
14329                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
14330                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
14331                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
14332                                 else if (FAKELIGHT_ENABLED)
14333                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
14334                                 else if (rsurface.uselightmaptexture)
14335                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
14336                                 else
14337                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
14338                                 // then apply the texture to it
14339                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
14340                                 R_Mesh_TexBind(0, layer->texture);
14341                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
14342                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
14343                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
14344                                 RSurf_DrawBatch_GL11_Unlit(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);
14345                         }
14346                         else
14347                         {
14348                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
14349                                 R_Mesh_TexBind(0, layer->texture);
14350                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
14351                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
14352                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
14353                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
14354                                         RSurf_DrawBatch_GL11_VertexShade(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);
14355                                 else
14356                                         RSurf_DrawBatch_GL11_VertexColor(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);
14357                         }
14358                         break;
14359                 case TEXTURELAYERTYPE_TEXTURE:
14360                         // singletexture unlit texture with transparency support
14361                         R_Mesh_TexBind(0, layer->texture);
14362                         R_Mesh_TexMatrix(0, &layer->texmatrix);
14363                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
14364                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
14365                         RSurf_DrawBatch_GL11_Unlit(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);
14366                         break;
14367                 case TEXTURELAYERTYPE_FOG:
14368                         // singletexture fogging
14369                         if (layer->texture)
14370                         {
14371                                 R_Mesh_TexBind(0, layer->texture);
14372                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
14373                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
14374                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
14375                         }
14376                         else
14377                         {
14378                                 R_Mesh_TexBind(0, 0);
14379                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
14380                         }
14381                         // generate a color array for the fog pass
14382                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
14383                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
14384                         RSurf_DrawBatch();
14385                         break;
14386                 default:
14387                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
14388                 }
14389         }
14390         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
14391         {
14392                 GL_DepthFunc(GL_LEQUAL);
14393                 GL_AlphaTest(false);
14394         }
14395 }
14396
14397 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
14398 {
14399         int vi;
14400         int j;
14401         r_vertexgeneric_t *batchvertex;
14402         float c[4];
14403
14404         GL_AlphaTest(false);
14405 //      R_Mesh_ResetTextureState();
14406         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14407
14408         if(rsurface.texture && rsurface.texture->currentskinframe)
14409         {
14410                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
14411                 c[3] *= rsurface.texture->currentalpha;
14412         }
14413         else
14414         {
14415                 c[0] = 1;
14416                 c[1] = 0;
14417                 c[2] = 1;
14418                 c[3] = 1;
14419         }
14420
14421         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
14422         {
14423                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
14424                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
14425                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
14426         }
14427
14428         // brighten it up (as texture value 127 means "unlit")
14429         c[0] *= 2 * r_refdef.view.colorscale;
14430         c[1] *= 2 * r_refdef.view.colorscale;
14431         c[2] *= 2 * r_refdef.view.colorscale;
14432
14433         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
14434                 c[3] *= r_wateralpha.value;
14435
14436         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
14437         {
14438                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14439                 GL_DepthMask(false);
14440         }
14441         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
14442         {
14443                 GL_BlendFunc(GL_ONE, GL_ONE);
14444                 GL_DepthMask(false);
14445         }
14446         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
14447         {
14448                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
14449                 GL_DepthMask(false);
14450         }
14451         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
14452         {
14453                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
14454                 GL_DepthMask(false);
14455         }
14456         else
14457         {
14458                 GL_BlendFunc(GL_ONE, GL_ZERO);
14459                 GL_DepthMask(writedepth);
14460         }
14461
14462         if (r_showsurfaces.integer == 3)
14463         {
14464                 rsurface.passcolor4f = NULL;
14465
14466                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
14467                 {
14468                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
14469
14470                         rsurface.passcolor4f = NULL;
14471                         rsurface.passcolor4f_vertexbuffer = 0;
14472                         rsurface.passcolor4f_bufferoffset = 0;
14473                 }
14474                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
14475                 {
14476                         qboolean applycolor = true;
14477                         float one = 1.0;
14478
14479                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
14480
14481                         r_refdef.lightmapintensity = 1;
14482                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
14483                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
14484                 }
14485                 else if (FAKELIGHT_ENABLED)
14486                 {
14487                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
14488
14489                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
14490                         RSurf_DrawBatch_GL11_ApplyFakeLight();
14491                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
14492                 }
14493                 else
14494                 {
14495                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
14496
14497                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
14498                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
14499                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
14500                 }
14501
14502                 if(!rsurface.passcolor4f)
14503                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
14504
14505                 RSurf_DrawBatch_GL11_ApplyAmbient();
14506                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
14507                 if(r_refdef.fogenabled)
14508                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
14509                 RSurf_DrawBatch_GL11_ClampColor();
14510
14511                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
14512                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14513                 RSurf_DrawBatch();
14514         }
14515         else if (!r_refdef.view.showdebug)
14516         {
14517                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
14518                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
14519                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
14520                 {
14521                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
14522                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
14523                 }
14524                 R_Mesh_PrepareVertices_Generic_Unlock();
14525                 RSurf_DrawBatch();
14526         }
14527         else if (r_showsurfaces.integer == 4)
14528         {
14529                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
14530                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
14531                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
14532                 {
14533                         unsigned char c = vi << 3;
14534                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
14535                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
14536                 }
14537                 R_Mesh_PrepareVertices_Generic_Unlock();
14538                 RSurf_DrawBatch();
14539         }
14540         else if (r_showsurfaces.integer == 2)
14541         {
14542                 const int *e;
14543                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
14544                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
14545                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
14546                 {
14547                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
14548                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
14549                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
14550                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
14551                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
14552                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
14553                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
14554                 }
14555                 R_Mesh_PrepareVertices_Generic_Unlock();
14556                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
14557         }
14558         else
14559         {
14560                 int texturesurfaceindex;
14561                 int k;
14562                 const msurface_t *surface;
14563                 unsigned char surfacecolor4ub[4];
14564                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
14565                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
14566                 vi = 0;
14567                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
14568                 {
14569                         surface = texturesurfacelist[texturesurfaceindex];
14570                         k = (int)(((size_t)surface) / sizeof(msurface_t));
14571                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
14572                         for (j = 0;j < surface->num_vertices;j++)
14573                         {
14574                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
14575                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
14576                                 vi++;
14577                         }
14578                 }
14579                 R_Mesh_PrepareVertices_Generic_Unlock();
14580                 RSurf_DrawBatch();
14581         }
14582 }
14583
14584 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
14585 {
14586         CHECKGLERROR
14587         RSurf_SetupDepthAndCulling();
14588         if (r_showsurfaces.integer)
14589         {
14590                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
14591                 return;
14592         }
14593         switch (vid.renderpath)
14594         {
14595         case RENDERPATH_GL20:
14596         case RENDERPATH_CGGL:
14597         case RENDERPATH_D3D9:
14598         case RENDERPATH_D3D10:
14599         case RENDERPATH_D3D11:
14600         case RENDERPATH_SOFT:
14601         case RENDERPATH_GLES2:
14602                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
14603                 break;
14604         case RENDERPATH_GL13:
14605                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
14606                 break;
14607         case RENDERPATH_GL11:
14608                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
14609                 break;
14610         }
14611         CHECKGLERROR
14612 }
14613
14614 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
14615 {
14616         CHECKGLERROR
14617         RSurf_SetupDepthAndCulling();
14618         if (r_showsurfaces.integer)
14619         {
14620                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
14621                 return;
14622         }
14623         switch (vid.renderpath)
14624         {
14625         case RENDERPATH_GL20:
14626         case RENDERPATH_CGGL:
14627         case RENDERPATH_D3D9:
14628         case RENDERPATH_D3D10:
14629         case RENDERPATH_D3D11:
14630         case RENDERPATH_SOFT:
14631         case RENDERPATH_GLES2:
14632                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
14633                 break;
14634         case RENDERPATH_GL13:
14635                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
14636                 break;
14637         case RENDERPATH_GL11:
14638                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
14639                 break;
14640         }
14641         CHECKGLERROR
14642 }
14643
14644 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
14645 {
14646         int i, j;
14647         int texturenumsurfaces, endsurface;
14648         texture_t *texture;
14649         const msurface_t *surface;
14650 #define MAXBATCH_TRANSPARENTSURFACES 256
14651         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
14652
14653         // if the model is static it doesn't matter what value we give for
14654         // wantnormals and wanttangents, so this logic uses only rules applicable
14655         // to a model, knowing that they are meaningless otherwise
14656         if (ent == r_refdef.scene.worldentity)
14657                 RSurf_ActiveWorldEntity();
14658         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14659                 RSurf_ActiveModelEntity(ent, false, false, false);
14660         else
14661         {
14662                 switch (vid.renderpath)
14663                 {
14664                 case RENDERPATH_GL20:
14665                 case RENDERPATH_CGGL:
14666                 case RENDERPATH_D3D9:
14667                 case RENDERPATH_D3D10:
14668                 case RENDERPATH_D3D11:
14669                 case RENDERPATH_SOFT:
14670                 case RENDERPATH_GLES2:
14671                         RSurf_ActiveModelEntity(ent, true, true, false);
14672                         break;
14673                 case RENDERPATH_GL13:
14674                 case RENDERPATH_GL11:
14675                         RSurf_ActiveModelEntity(ent, true, false, false);
14676                         break;
14677                 }
14678         }
14679
14680         if (r_transparentdepthmasking.integer)
14681         {
14682                 qboolean setup = false;
14683                 for (i = 0;i < numsurfaces;i = j)
14684                 {
14685                         j = i + 1;
14686                         surface = rsurface.modelsurfaces + surfacelist[i];
14687                         texture = surface->texture;
14688                         rsurface.texture = R_GetCurrentTexture(texture);
14689                         rsurface.lightmaptexture = NULL;
14690                         rsurface.deluxemaptexture = NULL;
14691                         rsurface.uselightmaptexture = false;
14692                         // scan ahead until we find a different texture
14693                         endsurface = min(i + 1024, numsurfaces);
14694                         texturenumsurfaces = 0;
14695                         texturesurfacelist[texturenumsurfaces++] = surface;
14696                         for (;j < endsurface;j++)
14697                         {
14698                                 surface = rsurface.modelsurfaces + surfacelist[j];
14699                                 if (texture != surface->texture)
14700                                         break;
14701                                 texturesurfacelist[texturenumsurfaces++] = surface;
14702                         }
14703                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
14704                                 continue;
14705                         // render the range of surfaces as depth
14706                         if (!setup)
14707                         {
14708                                 setup = true;
14709                                 GL_ColorMask(0,0,0,0);
14710                                 GL_Color(1,1,1,1);
14711                                 GL_DepthTest(true);
14712                                 GL_BlendFunc(GL_ONE, GL_ZERO);
14713                                 GL_DepthMask(true);
14714                                 GL_AlphaTest(false);
14715 //                              R_Mesh_ResetTextureState();
14716                                 R_SetupShader_DepthOrShadow();
14717                         }
14718                         RSurf_SetupDepthAndCulling();
14719                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
14720                         if (rsurface.batchvertex3fbuffer)
14721                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
14722                         else
14723                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
14724                         RSurf_DrawBatch();
14725                 }
14726                 if (setup)
14727                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
14728         }
14729
14730         for (i = 0;i < numsurfaces;i = j)
14731         {
14732                 j = i + 1;
14733                 surface = rsurface.modelsurfaces + surfacelist[i];
14734                 texture = surface->texture;
14735                 rsurface.texture = R_GetCurrentTexture(texture);
14736                 // scan ahead until we find a different texture
14737                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
14738                 texturenumsurfaces = 0;
14739                 texturesurfacelist[texturenumsurfaces++] = surface;
14740                 if(FAKELIGHT_ENABLED)
14741                 {
14742                         rsurface.lightmaptexture = NULL;
14743                         rsurface.deluxemaptexture = NULL;
14744                         rsurface.uselightmaptexture = false;
14745                         for (;j < endsurface;j++)
14746                         {
14747                                 surface = rsurface.modelsurfaces + surfacelist[j];
14748                                 if (texture != surface->texture)
14749                                         break;
14750                                 texturesurfacelist[texturenumsurfaces++] = surface;
14751                         }
14752                 }
14753                 else
14754                 {
14755                         rsurface.lightmaptexture = surface->lightmaptexture;
14756                         rsurface.deluxemaptexture = surface->deluxemaptexture;
14757                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
14758                         for (;j < endsurface;j++)
14759                         {
14760                                 surface = rsurface.modelsurfaces + surfacelist[j];
14761                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
14762                                         break;
14763                                 texturesurfacelist[texturenumsurfaces++] = surface;
14764                         }
14765                 }
14766                 // render the range of surfaces
14767                 if (ent == r_refdef.scene.worldentity)
14768                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
14769                 else
14770                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
14771         }
14772         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14773         GL_AlphaTest(false);
14774 }
14775
14776 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
14777 {
14778         // transparent surfaces get pushed off into the transparent queue
14779         int surfacelistindex;
14780         const msurface_t *surface;
14781         vec3_t tempcenter, center;
14782         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
14783         {
14784                 surface = texturesurfacelist[surfacelistindex];
14785                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
14786                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
14787                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
14788                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
14789                 if (queueentity->transparent_offset) // transparent offset
14790                 {
14791                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
14792                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
14793                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
14794                 }
14795                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
14796         }
14797 }
14798
14799 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
14800 {
14801         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
14802                 return;
14803         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
14804                 return;
14805         RSurf_SetupDepthAndCulling();
14806         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
14807         if (rsurface.batchvertex3fbuffer)
14808                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
14809         else
14810                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
14811         RSurf_DrawBatch();
14812 }
14813
14814 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
14815 {
14816         const entity_render_t *queueentity = r_refdef.scene.worldentity;
14817         CHECKGLERROR
14818         if (depthonly)
14819                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
14820         else if (prepass)
14821         {
14822                 if (!rsurface.texture->currentnumlayers)
14823                         return;
14824                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
14825                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
14826                 else
14827                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
14828         }
14829         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
14830                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
14831         else if (!rsurface.texture->currentnumlayers)
14832                 return;
14833         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
14834         {
14835                 // in the deferred case, transparent surfaces were queued during prepass
14836                 if (!r_shadow_usingdeferredprepass)
14837                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
14838         }
14839         else
14840         {
14841                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
14842                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
14843         }
14844         CHECKGLERROR
14845 }
14846
14847 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
14848 {
14849         int i, j;
14850         texture_t *texture;
14851         R_FrameData_SetMark();
14852         // break the surface list down into batches by texture and use of lightmapping
14853         for (i = 0;i < numsurfaces;i = j)
14854         {
14855                 j = i + 1;
14856                 // texture is the base texture pointer, rsurface.texture is the
14857                 // current frame/skin the texture is directing us to use (for example
14858                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
14859                 // use skin 1 instead)
14860                 texture = surfacelist[i]->texture;
14861                 rsurface.texture = R_GetCurrentTexture(texture);
14862                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
14863                 {
14864                         // if this texture is not the kind we want, skip ahead to the next one
14865                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
14866                                 ;
14867                         continue;
14868                 }
14869                 if(FAKELIGHT_ENABLED || depthonly || prepass)
14870                 {
14871                         rsurface.lightmaptexture = NULL;
14872                         rsurface.deluxemaptexture = NULL;
14873                         rsurface.uselightmaptexture = false;
14874                         // simply scan ahead until we find a different texture or lightmap state
14875                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
14876                                 ;
14877                 }
14878                 else
14879                 {
14880                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
14881                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
14882                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
14883                         // simply scan ahead until we find a different texture or lightmap state
14884                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
14885                                 ;
14886                 }
14887                 // render the range of surfaces
14888                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
14889         }
14890         R_FrameData_ReturnToMark();
14891 }
14892
14893 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
14894 {
14895         CHECKGLERROR
14896         if (depthonly)
14897                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
14898         else if (prepass)
14899         {
14900                 if (!rsurface.texture->currentnumlayers)
14901                         return;
14902                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
14903                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
14904                 else
14905                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
14906         }
14907         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
14908                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
14909         else if (!rsurface.texture->currentnumlayers)
14910                 return;
14911         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
14912         {
14913                 // in the deferred case, transparent surfaces were queued during prepass
14914                 if (!r_shadow_usingdeferredprepass)
14915                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
14916         }
14917         else
14918         {
14919                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
14920                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
14921         }
14922         CHECKGLERROR
14923 }
14924
14925 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
14926 {
14927         int i, j;
14928         texture_t *texture;
14929         R_FrameData_SetMark();
14930         // break the surface list down into batches by texture and use of lightmapping
14931         for (i = 0;i < numsurfaces;i = j)
14932         {
14933                 j = i + 1;
14934                 // texture is the base texture pointer, rsurface.texture is the
14935                 // current frame/skin the texture is directing us to use (for example
14936                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
14937                 // use skin 1 instead)
14938                 texture = surfacelist[i]->texture;
14939                 rsurface.texture = R_GetCurrentTexture(texture);
14940                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
14941                 {
14942                         // if this texture is not the kind we want, skip ahead to the next one
14943                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
14944                                 ;
14945                         continue;
14946                 }
14947                 if(FAKELIGHT_ENABLED || depthonly || prepass)
14948                 {
14949                         rsurface.lightmaptexture = NULL;
14950                         rsurface.deluxemaptexture = NULL;
14951                         rsurface.uselightmaptexture = false;
14952                         // simply scan ahead until we find a different texture or lightmap state
14953                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
14954                                 ;
14955                 }
14956                 else
14957                 {
14958                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
14959                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
14960                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
14961                         // simply scan ahead until we find a different texture or lightmap state
14962                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
14963                                 ;
14964                 }
14965                 // render the range of surfaces
14966                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
14967         }
14968         R_FrameData_ReturnToMark();
14969 }
14970
14971 float locboxvertex3f[6*4*3] =
14972 {
14973         1,0,1, 1,0,0, 1,1,0, 1,1,1,
14974         0,1,1, 0,1,0, 0,0,0, 0,0,1,
14975         1,1,1, 1,1,0, 0,1,0, 0,1,1,
14976         0,0,1, 0,0,0, 1,0,0, 1,0,1,
14977         0,0,1, 1,0,1, 1,1,1, 0,1,1,
14978         1,0,0, 0,0,0, 0,1,0, 1,1,0
14979 };
14980
14981 unsigned short locboxelements[6*2*3] =
14982 {
14983          0, 1, 2, 0, 2, 3,
14984          4, 5, 6, 4, 6, 7,
14985          8, 9,10, 8,10,11,
14986         12,13,14, 12,14,15,
14987         16,17,18, 16,18,19,
14988         20,21,22, 20,22,23
14989 };
14990
14991 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
14992 {
14993         int i, j;
14994         cl_locnode_t *loc = (cl_locnode_t *)ent;
14995         vec3_t mins, size;
14996         float vertex3f[6*4*3];
14997         CHECKGLERROR
14998         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14999         GL_DepthMask(false);
15000         GL_DepthRange(0, 1);
15001         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
15002         GL_DepthTest(true);
15003         GL_CullFace(GL_NONE);
15004         R_EntityMatrix(&identitymatrix);
15005
15006 //      R_Mesh_ResetTextureState();
15007
15008         i = surfacelist[0];
15009         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
15010                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
15011                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
15012                         surfacelist[0] < 0 ? 0.5f : 0.125f);
15013
15014         if (VectorCompare(loc->mins, loc->maxs))
15015         {
15016                 VectorSet(size, 2, 2, 2);
15017                 VectorMA(loc->mins, -0.5f, size, mins);
15018         }
15019         else
15020         {
15021                 VectorCopy(loc->mins, mins);
15022                 VectorSubtract(loc->maxs, loc->mins, size);
15023         }
15024
15025         for (i = 0;i < 6*4*3;)
15026                 for (j = 0;j < 3;j++, i++)
15027                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
15028
15029         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
15030         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
15031         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
15032 }
15033
15034 void R_DrawLocs(void)
15035 {
15036         int index;
15037         cl_locnode_t *loc, *nearestloc;
15038         vec3_t center;
15039         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
15040         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
15041         {
15042                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
15043                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
15044         }
15045 }
15046
15047 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
15048 {
15049         if (decalsystem->decals)
15050                 Mem_Free(decalsystem->decals);
15051         memset(decalsystem, 0, sizeof(*decalsystem));
15052 }
15053
15054 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)
15055 {
15056         tridecal_t *decal;
15057         tridecal_t *decals;
15058         int i;
15059
15060         // expand or initialize the system
15061         if (decalsystem->maxdecals <= decalsystem->numdecals)
15062         {
15063                 decalsystem_t old = *decalsystem;
15064                 qboolean useshortelements;
15065                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
15066                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
15067                 decalsystem->decals = (tridecal_t *)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)));
15068                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
15069                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
15070                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
15071                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
15072                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
15073                 if (decalsystem->numdecals)
15074                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
15075                 if (old.decals)
15076                         Mem_Free(old.decals);
15077                 for (i = 0;i < decalsystem->maxdecals*3;i++)
15078                         decalsystem->element3i[i] = i;
15079                 if (useshortelements)
15080                         for (i = 0;i < decalsystem->maxdecals*3;i++)
15081                                 decalsystem->element3s[i] = i;
15082         }
15083
15084         // grab a decal and search for another free slot for the next one
15085         decals = decalsystem->decals;
15086         decal = decalsystem->decals + (i = decalsystem->freedecal++);
15087         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
15088                 ;
15089         decalsystem->freedecal = i;
15090         if (decalsystem->numdecals <= i)
15091                 decalsystem->numdecals = i + 1;
15092
15093         // initialize the decal
15094         decal->lived = 0;
15095         decal->triangleindex = triangleindex;
15096         decal->surfaceindex = surfaceindex;
15097         decal->decalsequence = decalsequence;
15098         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
15099         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
15100         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
15101         decal->color4ub[0][3] = 255;
15102         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
15103         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
15104         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
15105         decal->color4ub[1][3] = 255;
15106         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
15107         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
15108         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
15109         decal->color4ub[2][3] = 255;
15110         decal->vertex3f[0][0] = v0[0];
15111         decal->vertex3f[0][1] = v0[1];
15112         decal->vertex3f[0][2] = v0[2];
15113         decal->vertex3f[1][0] = v1[0];
15114         decal->vertex3f[1][1] = v1[1];
15115         decal->vertex3f[1][2] = v1[2];
15116         decal->vertex3f[2][0] = v2[0];
15117         decal->vertex3f[2][1] = v2[1];
15118         decal->vertex3f[2][2] = v2[2];
15119         decal->texcoord2f[0][0] = t0[0];
15120         decal->texcoord2f[0][1] = t0[1];
15121         decal->texcoord2f[1][0] = t1[0];
15122         decal->texcoord2f[1][1] = t1[1];
15123         decal->texcoord2f[2][0] = t2[0];
15124         decal->texcoord2f[2][1] = t2[1];
15125 }
15126
15127 extern cvar_t cl_decals_bias;
15128 extern cvar_t cl_decals_models;
15129 extern cvar_t cl_decals_newsystem_intensitymultiplier;
15130 // baseparms, parms, temps
15131 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)
15132 {
15133         int cornerindex;
15134         int index;
15135         float v[9][3];
15136         const float *vertex3f;
15137         int numpoints;
15138         float points[2][9][3];
15139         float temp[3];
15140         float tc[9][2];
15141         float f;
15142         float c[9][4];
15143         const int *e;
15144
15145         e = rsurface.modelelement3i + 3*triangleindex;
15146
15147         vertex3f = rsurface.modelvertex3f;
15148
15149         for (cornerindex = 0;cornerindex < 3;cornerindex++)
15150         {
15151                 index = 3*e[cornerindex];
15152                 VectorCopy(vertex3f + index, v[cornerindex]);
15153         }
15154         // cull backfaces
15155         //TriangleNormal(v[0], v[1], v[2], normal);
15156         //if (DotProduct(normal, localnormal) < 0.0f)
15157         //      continue;
15158         // clip by each of the box planes formed from the projection matrix
15159         // if anything survives, we emit the decal
15160         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]);
15161         if (numpoints < 3)
15162                 return;
15163         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]);
15164         if (numpoints < 3)
15165                 return;
15166         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]);
15167         if (numpoints < 3)
15168                 return;
15169         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]);
15170         if (numpoints < 3)
15171                 return;
15172         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]);
15173         if (numpoints < 3)
15174                 return;
15175         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]);
15176         if (numpoints < 3)
15177                 return;
15178         // some part of the triangle survived, so we have to accept it...
15179         if (dynamic)
15180         {
15181                 // dynamic always uses the original triangle
15182                 numpoints = 3;
15183                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
15184                 {
15185                         index = 3*e[cornerindex];
15186                         VectorCopy(vertex3f + index, v[cornerindex]);
15187                 }
15188         }
15189         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
15190         {
15191                 // convert vertex positions to texcoords
15192                 Matrix4x4_Transform(projection, v[cornerindex], temp);
15193                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
15194                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
15195                 // calculate distance fade from the projection origin
15196                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
15197                 f = bound(0.0f, f, 1.0f);
15198                 c[cornerindex][0] = r * f;
15199                 c[cornerindex][1] = g * f;
15200                 c[cornerindex][2] = b * f;
15201                 c[cornerindex][3] = 1.0f;
15202                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
15203         }
15204         if (dynamic)
15205                 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);
15206         else
15207                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
15208                         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);
15209 }
15210 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)
15211 {
15212         matrix4x4_t projection;
15213         decalsystem_t *decalsystem;
15214         qboolean dynamic;
15215         dp_model_t *model;
15216         const msurface_t *surface;
15217         const msurface_t *surfaces;
15218         const int *surfacelist;
15219         const texture_t *texture;
15220         int numtriangles;
15221         int numsurfacelist;
15222         int surfacelistindex;
15223         int surfaceindex;
15224         int triangleindex;
15225         float localorigin[3];
15226         float localnormal[3];
15227         float localmins[3];
15228         float localmaxs[3];
15229         float localsize;
15230         //float normal[3];
15231         float planes[6][4];
15232         float angles[3];
15233         bih_t *bih;
15234         int bih_triangles_count;
15235         int bih_triangles[256];
15236         int bih_surfaces[256];
15237
15238         decalsystem = &ent->decalsystem;
15239         model = ent->model;
15240         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
15241         {
15242                 R_DecalSystem_Reset(&ent->decalsystem);
15243                 return;
15244         }
15245
15246         if (!model->brush.data_leafs && !cl_decals_models.integer)
15247         {
15248                 if (decalsystem->model)
15249                         R_DecalSystem_Reset(decalsystem);
15250                 return;
15251         }
15252
15253         if (decalsystem->model != model)
15254                 R_DecalSystem_Reset(decalsystem);
15255         decalsystem->model = model;
15256
15257         RSurf_ActiveModelEntity(ent, false, false, false);
15258
15259         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
15260         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
15261         VectorNormalize(localnormal);
15262         localsize = worldsize*rsurface.inversematrixscale;
15263         localmins[0] = localorigin[0] - localsize;
15264         localmins[1] = localorigin[1] - localsize;
15265         localmins[2] = localorigin[2] - localsize;
15266         localmaxs[0] = localorigin[0] + localsize;
15267         localmaxs[1] = localorigin[1] + localsize;
15268         localmaxs[2] = localorigin[2] + localsize;
15269
15270         //VectorCopy(localnormal, planes[4]);
15271         //VectorVectors(planes[4], planes[2], planes[0]);
15272         AnglesFromVectors(angles, localnormal, NULL, false);
15273         AngleVectors(angles, planes[0], planes[2], planes[4]);
15274         VectorNegate(planes[0], planes[1]);
15275         VectorNegate(planes[2], planes[3]);
15276         VectorNegate(planes[4], planes[5]);
15277         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
15278         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
15279         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
15280         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
15281         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
15282         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
15283
15284 #if 1
15285 // works
15286 {
15287         matrix4x4_t forwardprojection;
15288         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
15289         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
15290 }
15291 #else
15292 // broken
15293 {
15294         float projectionvector[4][3];
15295         VectorScale(planes[0], ilocalsize, projectionvector[0]);
15296         VectorScale(planes[2], ilocalsize, projectionvector[1]);
15297         VectorScale(planes[4], ilocalsize, projectionvector[2]);
15298         projectionvector[0][0] = planes[0][0] * ilocalsize;
15299         projectionvector[0][1] = planes[1][0] * ilocalsize;
15300         projectionvector[0][2] = planes[2][0] * ilocalsize;
15301         projectionvector[1][0] = planes[0][1] * ilocalsize;
15302         projectionvector[1][1] = planes[1][1] * ilocalsize;
15303         projectionvector[1][2] = planes[2][1] * ilocalsize;
15304         projectionvector[2][0] = planes[0][2] * ilocalsize;
15305         projectionvector[2][1] = planes[1][2] * ilocalsize;
15306         projectionvector[2][2] = planes[2][2] * ilocalsize;
15307         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
15308         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
15309         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
15310         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
15311 }
15312 #endif
15313
15314         dynamic = model->surfmesh.isanimated;
15315         numsurfacelist = model->nummodelsurfaces;
15316         surfacelist = model->sortedmodelsurfaces;
15317         surfaces = model->data_surfaces;
15318
15319         bih = NULL;
15320         bih_triangles_count = -1;
15321         if(!dynamic)
15322         {
15323                 if(model->render_bih.numleafs)
15324                         bih = &model->render_bih;
15325                 else if(model->collision_bih.numleafs)
15326                         bih = &model->collision_bih;
15327         }
15328         if(bih)
15329                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
15330         if(bih_triangles_count == 0)
15331                 return;
15332         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
15333                 return;
15334         if(bih_triangles_count > 0)
15335         {
15336                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
15337                 {
15338                         surfaceindex = bih_surfaces[triangleindex];
15339                         surface = surfaces + surfaceindex;
15340                         texture = surface->texture;
15341                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
15342                                 continue;
15343                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
15344                                 continue;
15345                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
15346                 }
15347         }
15348         else
15349         {
15350                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
15351                 {
15352                         surfaceindex = surfacelist[surfacelistindex];
15353                         surface = surfaces + surfaceindex;
15354                         // check cull box first because it rejects more than any other check
15355                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
15356                                 continue;
15357                         // skip transparent surfaces
15358                         texture = surface->texture;
15359                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
15360                                 continue;
15361                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
15362                                 continue;
15363                         numtriangles = surface->num_triangles;
15364                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
15365                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
15366                 }
15367         }
15368 }
15369
15370 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
15371 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)
15372 {
15373         int renderentityindex;
15374         float worldmins[3];
15375         float worldmaxs[3];
15376         entity_render_t *ent;
15377
15378         if (!cl_decals_newsystem.integer)
15379                 return;
15380
15381         worldmins[0] = worldorigin[0] - worldsize;
15382         worldmins[1] = worldorigin[1] - worldsize;
15383         worldmins[2] = worldorigin[2] - worldsize;
15384         worldmaxs[0] = worldorigin[0] + worldsize;
15385         worldmaxs[1] = worldorigin[1] + worldsize;
15386         worldmaxs[2] = worldorigin[2] + worldsize;
15387
15388         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
15389
15390         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
15391         {
15392                 ent = r_refdef.scene.entities[renderentityindex];
15393                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
15394                         continue;
15395
15396                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
15397         }
15398 }
15399
15400 typedef struct r_decalsystem_splatqueue_s
15401 {
15402         vec3_t worldorigin;
15403         vec3_t worldnormal;
15404         float color[4];
15405         float tcrange[4];
15406         float worldsize;
15407         int decalsequence;
15408 }
15409 r_decalsystem_splatqueue_t;
15410
15411 int r_decalsystem_numqueued = 0;
15412 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
15413
15414 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)
15415 {
15416         r_decalsystem_splatqueue_t *queue;
15417
15418         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
15419                 return;
15420
15421         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
15422         VectorCopy(worldorigin, queue->worldorigin);
15423         VectorCopy(worldnormal, queue->worldnormal);
15424         Vector4Set(queue->color, r, g, b, a);
15425         Vector4Set(queue->tcrange, s1, t1, s2, t2);
15426         queue->worldsize = worldsize;
15427         queue->decalsequence = cl.decalsequence++;
15428 }
15429
15430 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
15431 {
15432         int i;
15433         r_decalsystem_splatqueue_t *queue;
15434
15435         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
15436                 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);
15437         r_decalsystem_numqueued = 0;
15438 }
15439
15440 extern cvar_t cl_decals_max;
15441 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
15442 {
15443         int i;
15444         decalsystem_t *decalsystem = &ent->decalsystem;
15445         int numdecals;
15446         int killsequence;
15447         tridecal_t *decal;
15448         float frametime;
15449         float lifetime;
15450
15451         if (!decalsystem->numdecals)
15452                 return;
15453
15454         if (r_showsurfaces.integer)
15455                 return;
15456
15457         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
15458         {
15459                 R_DecalSystem_Reset(decalsystem);
15460                 return;
15461         }
15462
15463         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
15464         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
15465
15466         if (decalsystem->lastupdatetime)
15467                 frametime = (cl.time - decalsystem->lastupdatetime);
15468         else
15469                 frametime = 0;
15470         decalsystem->lastupdatetime = cl.time;
15471         decal = decalsystem->decals;
15472         numdecals = decalsystem->numdecals;
15473
15474         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
15475         {
15476                 if (decal->color4ub[0][3])
15477                 {
15478                         decal->lived += frametime;
15479                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
15480                         {
15481                                 memset(decal, 0, sizeof(*decal));
15482                                 if (decalsystem->freedecal > i)
15483                                         decalsystem->freedecal = i;
15484                         }
15485                 }
15486         }
15487         decal = decalsystem->decals;
15488         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
15489                 numdecals--;
15490
15491         // collapse the array by shuffling the tail decals into the gaps
15492         for (;;)
15493         {
15494                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
15495                         decalsystem->freedecal++;
15496                 if (decalsystem->freedecal == numdecals)
15497                         break;
15498                 decal[decalsystem->freedecal] = decal[--numdecals];
15499         }
15500
15501         decalsystem->numdecals = numdecals;
15502
15503         if (numdecals <= 0)
15504         {
15505                 // if there are no decals left, reset decalsystem
15506                 R_DecalSystem_Reset(decalsystem);
15507         }
15508 }
15509
15510 extern skinframe_t *decalskinframe;
15511 static void R_DrawModelDecals_Entity(entity_render_t *ent)
15512 {
15513         int i;
15514         decalsystem_t *decalsystem = &ent->decalsystem;
15515         int numdecals;
15516         tridecal_t *decal;
15517         float faderate;
15518         float alpha;
15519         float *v3f;
15520         float *c4f;
15521         float *t2f;
15522         const int *e;
15523         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
15524         int numtris = 0;
15525
15526         numdecals = decalsystem->numdecals;
15527         if (!numdecals)
15528                 return;
15529
15530         if (r_showsurfaces.integer)
15531                 return;
15532
15533         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
15534         {
15535                 R_DecalSystem_Reset(decalsystem);
15536                 return;
15537         }
15538
15539         // if the model is static it doesn't matter what value we give for
15540         // wantnormals and wanttangents, so this logic uses only rules applicable
15541         // to a model, knowing that they are meaningless otherwise
15542         if (ent == r_refdef.scene.worldentity)
15543                 RSurf_ActiveWorldEntity();
15544         else
15545                 RSurf_ActiveModelEntity(ent, false, false, false);
15546
15547         decalsystem->lastupdatetime = cl.time;
15548         decal = decalsystem->decals;
15549
15550         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
15551
15552         // update vertex positions for animated models
15553         v3f = decalsystem->vertex3f;
15554         c4f = decalsystem->color4f;
15555         t2f = decalsystem->texcoord2f;
15556         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
15557         {
15558                 if (!decal->color4ub[0][3])
15559                         continue;
15560
15561                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
15562                         continue;
15563
15564                 // update color values for fading decals
15565                 if (decal->lived >= cl_decals_time.value)
15566                 {
15567                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
15568                         alpha *= (1.0f/255.0f);
15569                 }
15570                 else
15571                         alpha = 1.0f/255.0f;
15572
15573                 c4f[ 0] = decal->color4ub[0][0] * alpha;
15574                 c4f[ 1] = decal->color4ub[0][1] * alpha;
15575                 c4f[ 2] = decal->color4ub[0][2] * alpha;
15576                 c4f[ 3] = 1;
15577                 c4f[ 4] = decal->color4ub[1][0] * alpha;
15578                 c4f[ 5] = decal->color4ub[1][1] * alpha;
15579                 c4f[ 6] = decal->color4ub[1][2] * alpha;
15580                 c4f[ 7] = 1;
15581                 c4f[ 8] = decal->color4ub[2][0] * alpha;
15582                 c4f[ 9] = decal->color4ub[2][1] * alpha;
15583                 c4f[10] = decal->color4ub[2][2] * alpha;
15584                 c4f[11] = 1;
15585
15586                 t2f[0] = decal->texcoord2f[0][0];
15587                 t2f[1] = decal->texcoord2f[0][1];
15588                 t2f[2] = decal->texcoord2f[1][0];
15589                 t2f[3] = decal->texcoord2f[1][1];
15590                 t2f[4] = decal->texcoord2f[2][0];
15591                 t2f[5] = decal->texcoord2f[2][1];
15592
15593                 // update vertex positions for animated models
15594                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
15595                 {
15596                         e = rsurface.modelelement3i + 3*decal->triangleindex;
15597                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
15598                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
15599                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
15600                 }
15601                 else
15602                 {
15603                         VectorCopy(decal->vertex3f[0], v3f);
15604                         VectorCopy(decal->vertex3f[1], v3f + 3);
15605                         VectorCopy(decal->vertex3f[2], v3f + 6);
15606                 }
15607
15608                 if (r_refdef.fogenabled)
15609                 {
15610                         alpha = RSurf_FogVertex(v3f);
15611                         VectorScale(c4f, alpha, c4f);
15612                         alpha = RSurf_FogVertex(v3f + 3);
15613                         VectorScale(c4f + 4, alpha, c4f + 4);
15614                         alpha = RSurf_FogVertex(v3f + 6);
15615                         VectorScale(c4f + 8, alpha, c4f + 8);
15616                 }
15617
15618                 v3f += 9;
15619                 c4f += 12;
15620                 t2f += 6;
15621                 numtris++;
15622         }
15623
15624         if (numtris > 0)
15625         {
15626                 r_refdef.stats.drawndecals += numtris;
15627
15628                 // now render the decals all at once
15629                 // (this assumes they all use one particle font texture!)
15630                 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);
15631 //              R_Mesh_ResetTextureState();
15632                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
15633                 GL_DepthMask(false);
15634                 GL_DepthRange(0, 1);
15635                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
15636                 GL_DepthTest(true);
15637                 GL_CullFace(GL_NONE);
15638                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
15639                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
15640                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
15641         }
15642 }
15643
15644 static void R_DrawModelDecals(void)
15645 {
15646         int i, numdecals;
15647
15648         // fade faster when there are too many decals
15649         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
15650         for (i = 0;i < r_refdef.scene.numentities;i++)
15651                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
15652
15653         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
15654         for (i = 0;i < r_refdef.scene.numentities;i++)
15655                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
15656                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
15657
15658         R_DecalSystem_ApplySplatEntitiesQueue();
15659
15660         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
15661         for (i = 0;i < r_refdef.scene.numentities;i++)
15662                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
15663
15664         r_refdef.stats.totaldecals += numdecals;
15665
15666         if (r_showsurfaces.integer)
15667                 return;
15668
15669         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
15670
15671         for (i = 0;i < r_refdef.scene.numentities;i++)
15672         {
15673                 if (!r_refdef.viewcache.entityvisible[i])
15674                         continue;
15675                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
15676                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
15677         }
15678 }
15679
15680 extern cvar_t mod_collision_bih;
15681 void R_DrawDebugModel(void)
15682 {
15683         entity_render_t *ent = rsurface.entity;
15684         int i, j, k, l, flagsmask;
15685         const msurface_t *surface;
15686         dp_model_t *model = ent->model;
15687         vec3_t v;
15688
15689         switch(vid.renderpath)
15690         {
15691         case RENDERPATH_GL11:
15692         case RENDERPATH_GL13:
15693         case RENDERPATH_GL20:
15694         case RENDERPATH_CGGL:
15695                 break;
15696         case RENDERPATH_D3D9:
15697                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
15698                 return;
15699         case RENDERPATH_D3D10:
15700                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
15701                 return;
15702         case RENDERPATH_D3D11:
15703                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
15704                 return;
15705         case RENDERPATH_SOFT:
15706                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
15707                 return;
15708         case RENDERPATH_GLES2:
15709                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
15710                 break;
15711         }
15712
15713         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
15714
15715 //      R_Mesh_ResetTextureState();
15716         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
15717         GL_DepthRange(0, 1);
15718         GL_DepthTest(!r_showdisabledepthtest.integer);
15719         GL_DepthMask(false);
15720         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
15721
15722         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
15723         {
15724                 int triangleindex;
15725                 int bihleafindex;
15726                 qboolean cullbox = ent == r_refdef.scene.worldentity;
15727                 const q3mbrush_t *brush;
15728                 const bih_t *bih = &model->collision_bih;
15729                 const bih_leaf_t *bihleaf;
15730                 float vertex3f[3][3];
15731                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
15732                 cullbox = false;
15733                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
15734                 {
15735                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
15736                                 continue;
15737                         switch (bihleaf->type)
15738                         {
15739                         case BIH_BRUSH:
15740                                 brush = model->brush.data_brushes + bihleaf->itemindex;
15741                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
15742                                 {
15743                                         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);
15744                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
15745                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
15746                                 }
15747                                 break;
15748                         case BIH_COLLISIONTRIANGLE:
15749                                 triangleindex = bihleaf->itemindex;
15750                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
15751                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
15752                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
15753                                 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);
15754                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
15755                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
15756                                 break;
15757                         case BIH_RENDERTRIANGLE:
15758                                 triangleindex = bihleaf->itemindex;
15759                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
15760                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
15761                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
15762                                 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);
15763                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
15764                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
15765                                 break;
15766                         }
15767                 }
15768         }
15769
15770         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
15771
15772         if (r_showtris.integer || (r_shownormals.value != 0))
15773         {
15774                 if (r_showdisabledepthtest.integer)
15775                 {
15776                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
15777                         GL_DepthMask(false);
15778                 }
15779                 else
15780                 {
15781                         GL_BlendFunc(GL_ONE, GL_ZERO);
15782                         GL_DepthMask(true);
15783                 }
15784                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
15785                 {
15786                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
15787                                 continue;
15788                         rsurface.texture = R_GetCurrentTexture(surface->texture);
15789                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
15790                         {
15791                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
15792                                 if (r_showtris.value > 0)
15793                                 {
15794                                         if (!rsurface.texture->currentlayers->depthmask)
15795                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
15796                                         else if (ent == r_refdef.scene.worldentity)
15797                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
15798                                         else
15799                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
15800                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
15801                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
15802                                         RSurf_DrawBatch();
15803                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
15804                                         CHECKGLERROR
15805                                 }
15806                                 if (r_shownormals.value < 0)
15807                                 {
15808                                         qglBegin(GL_LINES);
15809                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
15810                                         {
15811                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
15812                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
15813                                                 qglVertex3f(v[0], v[1], v[2]);
15814                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
15815                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
15816                                                 qglVertex3f(v[0], v[1], v[2]);
15817                                         }
15818                                         qglEnd();
15819                                         CHECKGLERROR
15820                                 }
15821                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
15822                                 {
15823                                         qglBegin(GL_LINES);
15824                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
15825                                         {
15826                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
15827                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
15828                                                 qglVertex3f(v[0], v[1], v[2]);
15829                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
15830                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
15831                                                 qglVertex3f(v[0], v[1], v[2]);
15832                                         }
15833                                         qglEnd();
15834                                         CHECKGLERROR
15835                                         qglBegin(GL_LINES);
15836                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
15837                                         {
15838                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
15839                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
15840                                                 qglVertex3f(v[0], v[1], v[2]);
15841                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
15842                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
15843                                                 qglVertex3f(v[0], v[1], v[2]);
15844                                         }
15845                                         qglEnd();
15846                                         CHECKGLERROR
15847                                         qglBegin(GL_LINES);
15848                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
15849                                         {
15850                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
15851                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
15852                                                 qglVertex3f(v[0], v[1], v[2]);
15853                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
15854                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
15855                                                 qglVertex3f(v[0], v[1], v[2]);
15856                                         }
15857                                         qglEnd();
15858                                         CHECKGLERROR
15859                                 }
15860                         }
15861                 }
15862                 rsurface.texture = NULL;
15863         }
15864 }
15865
15866 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
15867 int r_maxsurfacelist = 0;
15868 const msurface_t **r_surfacelist = NULL;
15869 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
15870 {
15871         int i, j, endj, flagsmask;
15872         dp_model_t *model = r_refdef.scene.worldmodel;
15873         msurface_t *surfaces;
15874         unsigned char *update;
15875         int numsurfacelist = 0;
15876         if (model == NULL)
15877                 return;
15878
15879         if (r_maxsurfacelist < model->num_surfaces)
15880         {
15881                 r_maxsurfacelist = model->num_surfaces;
15882                 if (r_surfacelist)
15883                         Mem_Free((msurface_t**)r_surfacelist);
15884                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
15885         }
15886
15887         RSurf_ActiveWorldEntity();
15888
15889         surfaces = model->data_surfaces;
15890         update = model->brushq1.lightmapupdateflags;
15891
15892         // update light styles on this submodel
15893         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
15894         {
15895                 model_brush_lightstyleinfo_t *style;
15896                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
15897                 {
15898                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
15899                         {
15900                                 int *list = style->surfacelist;
15901                                 style->value = r_refdef.scene.lightstylevalue[style->style];
15902                                 for (j = 0;j < style->numsurfaces;j++)
15903                                         update[list[j]] = true;
15904                         }
15905                 }
15906         }
15907
15908         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
15909
15910         if (debug)
15911         {
15912                 R_DrawDebugModel();
15913                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
15914                 return;
15915         }
15916
15917         rsurface.lightmaptexture = NULL;
15918         rsurface.deluxemaptexture = NULL;
15919         rsurface.uselightmaptexture = false;
15920         rsurface.texture = NULL;
15921         rsurface.rtlight = NULL;
15922         numsurfacelist = 0;
15923         // add visible surfaces to draw list
15924         for (i = 0;i < model->nummodelsurfaces;i++)
15925         {
15926                 j = model->sortedmodelsurfaces[i];
15927                 if (r_refdef.viewcache.world_surfacevisible[j])
15928                         r_surfacelist[numsurfacelist++] = surfaces + j;
15929         }
15930         // update lightmaps if needed
15931         if (model->brushq1.firstrender)
15932         {
15933                 model->brushq1.firstrender = false;
15934                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
15935                         if (update[j])
15936                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
15937         }
15938         else if (update)
15939         {
15940                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
15941                         if (r_refdef.viewcache.world_surfacevisible[j])
15942                                 if (update[j])
15943                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
15944         }
15945         // don't do anything if there were no surfaces
15946         if (!numsurfacelist)
15947         {
15948                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
15949                 return;
15950         }
15951         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
15952         GL_AlphaTest(false);
15953
15954         // add to stats if desired
15955         if (r_speeds.integer && !skysurfaces && !depthonly)
15956         {
15957                 r_refdef.stats.world_surfaces += numsurfacelist;
15958                 for (j = 0;j < numsurfacelist;j++)
15959                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
15960         }
15961
15962         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
15963 }
15964
15965 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
15966 {
15967         int i, j, endj, flagsmask;
15968         dp_model_t *model = ent->model;
15969         msurface_t *surfaces;
15970         unsigned char *update;
15971         int numsurfacelist = 0;
15972         if (model == NULL)
15973                 return;
15974
15975         if (r_maxsurfacelist < model->num_surfaces)
15976         {
15977                 r_maxsurfacelist = model->num_surfaces;
15978                 if (r_surfacelist)
15979                         Mem_Free((msurface_t **)r_surfacelist);
15980                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
15981         }
15982
15983         // if the model is static it doesn't matter what value we give for
15984         // wantnormals and wanttangents, so this logic uses only rules applicable
15985         // to a model, knowing that they are meaningless otherwise
15986         if (ent == r_refdef.scene.worldentity)
15987                 RSurf_ActiveWorldEntity();
15988         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
15989                 RSurf_ActiveModelEntity(ent, false, false, false);
15990         else if (prepass)
15991                 RSurf_ActiveModelEntity(ent, true, true, true);
15992         else if (depthonly)
15993         {
15994                 switch (vid.renderpath)
15995                 {
15996                 case RENDERPATH_GL20:
15997                 case RENDERPATH_CGGL:
15998                 case RENDERPATH_D3D9:
15999                 case RENDERPATH_D3D10:
16000                 case RENDERPATH_D3D11:
16001                 case RENDERPATH_SOFT:
16002                 case RENDERPATH_GLES2:
16003                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
16004                         break;
16005                 case RENDERPATH_GL13:
16006                 case RENDERPATH_GL11:
16007                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
16008                         break;
16009                 }
16010         }
16011         else
16012         {
16013                 switch (vid.renderpath)
16014                 {
16015                 case RENDERPATH_GL20:
16016                 case RENDERPATH_CGGL:
16017                 case RENDERPATH_D3D9:
16018                 case RENDERPATH_D3D10:
16019                 case RENDERPATH_D3D11:
16020                 case RENDERPATH_SOFT:
16021                 case RENDERPATH_GLES2:
16022                         RSurf_ActiveModelEntity(ent, true, true, false);
16023                         break;
16024                 case RENDERPATH_GL13:
16025                 case RENDERPATH_GL11:
16026                         RSurf_ActiveModelEntity(ent, true, false, false);
16027                         break;
16028                 }
16029         }
16030
16031         surfaces = model->data_surfaces;
16032         update = model->brushq1.lightmapupdateflags;
16033
16034         // update light styles
16035         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
16036         {
16037                 model_brush_lightstyleinfo_t *style;
16038                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
16039                 {
16040                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
16041                         {
16042                                 int *list = style->surfacelist;
16043                                 style->value = r_refdef.scene.lightstylevalue[style->style];
16044                                 for (j = 0;j < style->numsurfaces;j++)
16045                                         update[list[j]] = true;
16046                         }
16047                 }
16048         }
16049
16050         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
16051
16052         if (debug)
16053         {
16054                 R_DrawDebugModel();
16055                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
16056                 return;
16057         }
16058
16059         rsurface.lightmaptexture = NULL;
16060         rsurface.deluxemaptexture = NULL;
16061         rsurface.uselightmaptexture = false;
16062         rsurface.texture = NULL;
16063         rsurface.rtlight = NULL;
16064         numsurfacelist = 0;
16065         // add visible surfaces to draw list
16066         for (i = 0;i < model->nummodelsurfaces;i++)
16067                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
16068         // don't do anything if there were no surfaces
16069         if (!numsurfacelist)
16070         {
16071                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
16072                 return;
16073         }
16074         // update lightmaps if needed
16075         if (update)
16076         {
16077                 int updated = 0;
16078                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
16079                 {
16080                         if (update[j])
16081                         {
16082                                 updated++;
16083                                 R_BuildLightMap(ent, surfaces + j);
16084                         }
16085                 }
16086         }
16087         if (update)
16088                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
16089                         if (update[j])
16090                                 R_BuildLightMap(ent, surfaces + j);
16091         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
16092         GL_AlphaTest(false);
16093
16094         // add to stats if desired
16095         if (r_speeds.integer && !skysurfaces && !depthonly)
16096         {
16097                 r_refdef.stats.entities_surfaces += numsurfacelist;
16098                 for (j = 0;j < numsurfacelist;j++)
16099                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
16100         }
16101
16102         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
16103 }
16104
16105 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
16106 {
16107         static texture_t texture;
16108         static msurface_t surface;
16109         const msurface_t *surfacelist = &surface;
16110
16111         // fake enough texture and surface state to render this geometry
16112
16113         texture.update_lastrenderframe = -1; // regenerate this texture
16114         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
16115         texture.currentskinframe = skinframe;
16116         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
16117         texture.offsetmapping = OFFSETMAPPING_OFF;
16118         texture.offsetscale = 1;
16119         texture.specularscalemod = 1;
16120         texture.specularpowermod = 1;
16121
16122         surface.texture = &texture;
16123         surface.num_triangles = numtriangles;
16124         surface.num_firsttriangle = firsttriangle;
16125         surface.num_vertices = numvertices;
16126         surface.num_firstvertex = firstvertex;
16127
16128         // now render it
16129         rsurface.texture = R_GetCurrentTexture(surface.texture);
16130         rsurface.lightmaptexture = NULL;
16131         rsurface.deluxemaptexture = NULL;
16132         rsurface.uselightmaptexture = false;
16133         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
16134 }
16135
16136 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)
16137 {
16138         static msurface_t surface;
16139         const msurface_t *surfacelist = &surface;
16140
16141         // fake enough texture and surface state to render this geometry
16142         surface.texture = texture;
16143         surface.num_triangles = numtriangles;
16144         surface.num_firsttriangle = firsttriangle;
16145         surface.num_vertices = numvertices;
16146         surface.num_firstvertex = firstvertex;
16147
16148         // now render it
16149         rsurface.texture = R_GetCurrentTexture(surface.texture);
16150         rsurface.lightmaptexture = NULL;
16151         rsurface.deluxemaptexture = NULL;
16152         rsurface.uselightmaptexture = false;
16153         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
16154 }