]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
196c4fefd580122c02d3e65e0dc43b2f3375b9fc
[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                 CHECKGLERROR
5211                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
5212         }
5213         else
5214                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
5215
5216         // free the strings
5217         if (vertexstring)
5218                 Mem_Free(vertexstring);
5219         if (geometrystring)
5220                 Mem_Free(geometrystring);
5221         if (fragmentstring)
5222                 Mem_Free(fragmentstring);
5223 }
5224
5225 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
5226 {
5227         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
5228         if (r_glsl_permutation != perm)
5229         {
5230                 r_glsl_permutation = perm;
5231                 if (!r_glsl_permutation->program)
5232                 {
5233                         if (!r_glsl_permutation->compiled)
5234                                 R_GLSL_CompilePermutation(perm, mode, permutation);
5235                         if (!r_glsl_permutation->program)
5236                         {
5237                                 // remove features until we find a valid permutation
5238                                 int i;
5239                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5240                                 {
5241                                         // reduce i more quickly whenever it would not remove any bits
5242                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
5243                                         if (!(permutation & j))
5244                                                 continue;
5245                                         permutation -= j;
5246                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
5247                                         if (!r_glsl_permutation->compiled)
5248                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
5249                                         if (r_glsl_permutation->program)
5250                                                 break;
5251                                 }
5252                                 if (i >= SHADERPERMUTATION_COUNT)
5253                                 {
5254                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
5255                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
5256                                         qglUseProgram(0);CHECKGLERROR
5257                                         return; // no bit left to clear, entire mode is broken
5258                                 }
5259                         }
5260                 }
5261                 CHECKGLERROR
5262                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
5263         }
5264         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5265         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5266         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
5267 }
5268
5269 #ifdef SUPPORTCG
5270 #include <Cg/cgGL.h>
5271 struct r_cg_permutation_s;
5272 typedef struct r_cg_permutation_s
5273 {
5274         /// hash lookup data
5275         struct r_cg_permutation_s *hashnext;
5276         unsigned int mode;
5277         unsigned int permutation;
5278
5279         /// indicates if we have tried compiling this permutation already
5280         qboolean compiled;
5281         /// 0 if compilation failed
5282         CGprogram vprogram;
5283         CGprogram fprogram;
5284         /// locations of detected parameters in programs, or NULL if not found
5285         CGparameter vp_EyePosition;
5286         CGparameter vp_FogPlane;
5287         CGparameter vp_LightDir;
5288         CGparameter vp_LightPosition;
5289         CGparameter vp_ModelToLight;
5290         CGparameter vp_TexMatrix;
5291         CGparameter vp_BackgroundTexMatrix;
5292         CGparameter vp_ModelViewProjectionMatrix;
5293         CGparameter vp_ModelViewMatrix;
5294         CGparameter vp_ShadowMapMatrix;
5295
5296         CGparameter fp_Texture_First;
5297         CGparameter fp_Texture_Second;
5298         CGparameter fp_Texture_GammaRamps;
5299         CGparameter fp_Texture_Normal;
5300         CGparameter fp_Texture_Color;
5301         CGparameter fp_Texture_Gloss;
5302         CGparameter fp_Texture_Glow;
5303         CGparameter fp_Texture_SecondaryNormal;
5304         CGparameter fp_Texture_SecondaryColor;
5305         CGparameter fp_Texture_SecondaryGloss;
5306         CGparameter fp_Texture_SecondaryGlow;
5307         CGparameter fp_Texture_Pants;
5308         CGparameter fp_Texture_Shirt;
5309         CGparameter fp_Texture_FogHeightTexture;
5310         CGparameter fp_Texture_FogMask;
5311         CGparameter fp_Texture_Lightmap;
5312         CGparameter fp_Texture_Deluxemap;
5313         CGparameter fp_Texture_Attenuation;
5314         CGparameter fp_Texture_Cube;
5315         CGparameter fp_Texture_Refraction;
5316         CGparameter fp_Texture_Reflection;
5317         CGparameter fp_Texture_ShadowMap2D;
5318         CGparameter fp_Texture_CubeProjection;
5319         CGparameter fp_Texture_ScreenDepth;
5320         CGparameter fp_Texture_ScreenNormalMap;
5321         CGparameter fp_Texture_ScreenDiffuse;
5322         CGparameter fp_Texture_ScreenSpecular;
5323         CGparameter fp_Texture_ReflectMask;
5324         CGparameter fp_Texture_ReflectCube;
5325         CGparameter fp_Alpha;
5326         CGparameter fp_BloomBlur_Parameters;
5327         CGparameter fp_ClientTime;
5328         CGparameter fp_Color_Ambient;
5329         CGparameter fp_Color_Diffuse;
5330         CGparameter fp_Color_Specular;
5331         CGparameter fp_Color_Glow;
5332         CGparameter fp_Color_Pants;
5333         CGparameter fp_Color_Shirt;
5334         CGparameter fp_DeferredColor_Ambient;
5335         CGparameter fp_DeferredColor_Diffuse;
5336         CGparameter fp_DeferredColor_Specular;
5337         CGparameter fp_DeferredMod_Diffuse;
5338         CGparameter fp_DeferredMod_Specular;
5339         CGparameter fp_DistortScaleRefractReflect;
5340         CGparameter fp_EyePosition;
5341         CGparameter fp_FogColor;
5342         CGparameter fp_FogHeightFade;
5343         CGparameter fp_FogPlane;
5344         CGparameter fp_FogPlaneViewDist;
5345         CGparameter fp_FogRangeRecip;
5346         CGparameter fp_LightColor;
5347         CGparameter fp_LightDir;
5348         CGparameter fp_LightPosition;
5349         CGparameter fp_OffsetMapping_Scale;
5350         CGparameter fp_PixelSize;
5351         CGparameter fp_ReflectColor;
5352         CGparameter fp_ReflectFactor;
5353         CGparameter fp_ReflectOffset;
5354         CGparameter fp_RefractColor;
5355         CGparameter fp_Saturation;
5356         CGparameter fp_ScreenCenterRefractReflect;
5357         CGparameter fp_ScreenScaleRefractReflect;
5358         CGparameter fp_ScreenToDepth;
5359         CGparameter fp_ShadowMap_Parameters;
5360         CGparameter fp_ShadowMap_TextureScale;
5361         CGparameter fp_SpecularPower;
5362         CGparameter fp_UserVec1;
5363         CGparameter fp_UserVec2;
5364         CGparameter fp_UserVec3;
5365         CGparameter fp_UserVec4;
5366         CGparameter fp_ViewTintColor;
5367         CGparameter fp_ViewToLight;
5368         CGparameter fp_PixelToScreenTexCoord;
5369         CGparameter fp_ModelToReflectCube;
5370         CGparameter fp_BloomColorSubtract;
5371         CGparameter fp_NormalmapScrollBlend;
5372 }
5373 r_cg_permutation_t;
5374
5375 /// information about each possible shader permutation
5376 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
5377 /// currently selected permutation
5378 r_cg_permutation_t *r_cg_permutation;
5379 /// storage for permutations linked in the hash table
5380 memexpandablearray_t r_cg_permutationarray;
5381
5382 #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));}}
5383
5384 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
5385 {
5386         //unsigned int hashdepth = 0;
5387         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
5388         r_cg_permutation_t *p;
5389         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
5390         {
5391                 if (p->mode == mode && p->permutation == permutation)
5392                 {
5393                         //if (hashdepth > 10)
5394                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
5395                         return p;
5396                 }
5397                 //hashdepth++;
5398         }
5399         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
5400         p->mode = mode;
5401         p->permutation = permutation;
5402         p->hashnext = r_cg_permutationhash[mode][hashindex];
5403         r_cg_permutationhash[mode][hashindex] = p;
5404         //if (hashdepth > 10)
5405         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
5406         return p;
5407 }
5408
5409 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
5410 {
5411         char *shaderstring;
5412         if (!filename || !filename[0])
5413                 return NULL;
5414         if (!strcmp(filename, "cg/default.cg"))
5415         {
5416                 if (!cgshaderstring)
5417                 {
5418                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
5419                         if (cgshaderstring)
5420                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
5421                         else
5422                                 cgshaderstring = (char *)builtincgshaderstring;
5423                 }
5424                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
5425                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
5426                 return shaderstring;
5427         }
5428         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
5429         if (shaderstring)
5430         {
5431                 if (printfromdisknotice)
5432                         Con_DPrintf("from disk %s... ", filename);
5433                 return shaderstring;
5434         }
5435         return shaderstring;
5436 }
5437
5438 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
5439 {
5440         // TODO: load or create .fp and .vp shader files
5441 }
5442
5443 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
5444 {
5445         int i;
5446         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
5447         int vertstring_length = 0;
5448         int geomstring_length = 0;
5449         int fragstring_length = 0;
5450         char *t;
5451         char *vertexstring, *geometrystring, *fragmentstring;
5452         char *vertstring, *geomstring, *fragstring;
5453         char permutationname[256];
5454         char cachename[256];
5455         CGprofile vertexProfile;
5456         CGprofile fragmentProfile;
5457         int vertstrings_count = 0;
5458         int geomstrings_count = 0;
5459         int fragstrings_count = 0;
5460         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
5461         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
5462         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
5463
5464         if (p->compiled)
5465                 return;
5466         p->compiled = true;
5467         p->vprogram = NULL;
5468         p->fprogram = NULL;
5469
5470         permutationname[0] = 0;
5471         cachename[0] = 0;
5472         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
5473         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
5474         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
5475
5476         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
5477         strlcat(cachename, "cg/", sizeof(cachename));
5478
5479         // the first pretext is which type of shader to compile as
5480         // (later these will all be bound together as a program object)
5481         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
5482         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
5483         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
5484
5485         // the second pretext is the mode (for example a light source)
5486         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
5487         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
5488         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
5489         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
5490         strlcat(cachename, modeinfo->name, sizeof(cachename));
5491
5492         // now add all the permutation pretexts
5493         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5494         {
5495                 if (permutation & (1<<i))
5496                 {
5497                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
5498                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
5499                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
5500                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
5501                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
5502                 }
5503                 else
5504                 {
5505                         // keep line numbers correct
5506                         vertstrings_list[vertstrings_count++] = "\n";
5507                         geomstrings_list[geomstrings_count++] = "\n";
5508                         fragstrings_list[fragstrings_count++] = "\n";
5509                 }
5510         }
5511
5512         // add static parms
5513         R_CompileShader_AddStaticParms(mode, permutation);
5514         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
5515         vertstrings_count += shaderstaticparms_count;
5516         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
5517         geomstrings_count += shaderstaticparms_count;
5518         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
5519         fragstrings_count += shaderstaticparms_count;
5520
5521         // replace spaces in the cachename with _ characters
5522         for (i = 0;cachename[i];i++)
5523                 if (cachename[i] == ' ')
5524                         cachename[i] = '_';
5525
5526         // now append the shader text itself
5527         vertstrings_list[vertstrings_count++] = vertexstring;
5528         geomstrings_list[geomstrings_count++] = geometrystring;
5529         fragstrings_list[fragstrings_count++] = fragmentstring;
5530
5531         // if any sources were NULL, clear the respective list
5532         if (!vertexstring)
5533                 vertstrings_count = 0;
5534         if (!geometrystring)
5535                 geomstrings_count = 0;
5536         if (!fragmentstring)
5537                 fragstrings_count = 0;
5538
5539         vertstring_length = 0;
5540         for (i = 0;i < vertstrings_count;i++)
5541                 vertstring_length += strlen(vertstrings_list[i]);
5542         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
5543         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
5544                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
5545
5546         geomstring_length = 0;
5547         for (i = 0;i < geomstrings_count;i++)
5548                 geomstring_length += strlen(geomstrings_list[i]);
5549         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
5550         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
5551                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
5552
5553         fragstring_length = 0;
5554         for (i = 0;i < fragstrings_count;i++)
5555                 fragstring_length += strlen(fragstrings_list[i]);
5556         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
5557         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
5558                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
5559
5560         CHECKGLERROR
5561         CHECKCGERROR
5562         //vertexProfile = CG_PROFILE_ARBVP1;
5563         //fragmentProfile = CG_PROFILE_ARBFP1;
5564         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
5565         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
5566         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
5567         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
5568         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
5569         CHECKGLERROR
5570
5571         // try to load the cached shader, or generate one
5572         R_CG_CacheShader(p, cachename, vertstring, fragstring);
5573
5574         // if caching failed, do a dynamic compile for now
5575         CHECKCGERROR
5576         if (vertstring[0] && !p->vprogram)
5577                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
5578         CHECKCGERROR
5579         if (fragstring[0] && !p->fprogram)
5580                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
5581         CHECKCGERROR
5582
5583         // look up all the uniform variable names we care about, so we don't
5584         // have to look them up every time we set them
5585         if (p->vprogram)
5586         {
5587                 CHECKCGERROR
5588                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
5589                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
5590                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
5591                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
5592                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
5593                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
5594                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
5595                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
5596                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
5597                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
5598                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
5599                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
5600                 CHECKCGERROR
5601         }
5602         if (p->fprogram)
5603         {
5604                 CHECKCGERROR
5605                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
5606                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
5607                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
5608                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
5609                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
5610                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
5611                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
5612                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
5613                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
5614                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
5615                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
5616                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
5617                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
5618                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
5619                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
5620                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
5621                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
5622                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
5623                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
5624                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
5625                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
5626                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
5627                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
5628                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
5629                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
5630                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
5631                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
5632                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
5633                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
5634                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
5635                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
5636                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
5637                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
5638                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
5639                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
5640                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
5641                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
5642                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
5643                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
5644                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
5645                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
5646                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
5647                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
5648                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
5649                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
5650                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
5651                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
5652                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
5653                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
5654                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
5655                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
5656                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
5657                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
5658                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
5659                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
5660                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
5661                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
5662                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
5663                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
5664                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
5665                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
5666                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
5667                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
5668                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
5669                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
5670                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
5671                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
5672                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
5673                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
5674                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
5675                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
5676                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
5677                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
5678                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
5679                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
5680                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
5681                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
5682                 p->fp_NormalmapScrollBlend       = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
5683                 CHECKCGERROR
5684         }
5685
5686         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
5687                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
5688         else
5689                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
5690
5691         // free the strings
5692         if (vertstring)
5693                 Mem_Free(vertstring);
5694         if (geomstring)
5695                 Mem_Free(geomstring);
5696         if (fragstring)
5697                 Mem_Free(fragstring);
5698         if (vertexstring)
5699                 Mem_Free(vertexstring);
5700         if (geometrystring)
5701                 Mem_Free(geometrystring);
5702         if (fragmentstring)
5703                 Mem_Free(fragmentstring);
5704 }
5705
5706 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
5707 {
5708         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
5709         CHECKGLERROR
5710         CHECKCGERROR
5711         if (r_cg_permutation != perm)
5712         {
5713                 r_cg_permutation = perm;
5714                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
5715                 {
5716                         if (!r_cg_permutation->compiled)
5717                                 R_CG_CompilePermutation(perm, mode, permutation);
5718                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
5719                         {
5720                                 // remove features until we find a valid permutation
5721                                 int i;
5722                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5723                                 {
5724                                         // reduce i more quickly whenever it would not remove any bits
5725                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
5726                                         if (!(permutation & j))
5727                                                 continue;
5728                                         permutation -= j;
5729                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
5730                                         if (!r_cg_permutation->compiled)
5731                                                 R_CG_CompilePermutation(perm, mode, permutation);
5732                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
5733                                                 break;
5734                                 }
5735                                 if (i >= SHADERPERMUTATION_COUNT)
5736                                 {
5737                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
5738                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
5739                                         return; // no bit left to clear, entire mode is broken
5740                                 }
5741                         }
5742                 }
5743                 CHECKGLERROR
5744                 CHECKCGERROR
5745                 if (r_cg_permutation->vprogram)
5746                 {
5747                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
5748                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
5749                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5750                 }
5751                 else
5752                 {
5753                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5754                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5755                 }
5756                 if (r_cg_permutation->fprogram)
5757                 {
5758                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
5759                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
5760                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5761                 }
5762                 else
5763                 {
5764                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5765                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5766                 }
5767         }
5768         CHECKCGERROR
5769         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
5770         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
5771         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
5772 }
5773
5774 void CG_BindTexture(CGparameter param, rtexture_t *tex)
5775 {
5776         cgGLSetTextureParameter(param, R_GetTexture(tex));
5777         cgGLEnableTextureParameter(param);
5778 }
5779 #endif
5780
5781 #ifdef SUPPORTD3D
5782
5783 #ifdef SUPPORTD3D
5784 #include <d3d9.h>
5785 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
5786 extern D3DCAPS9 vid_d3d9caps;
5787 #endif
5788
5789 struct r_hlsl_permutation_s;
5790 typedef struct r_hlsl_permutation_s
5791 {
5792         /// hash lookup data
5793         struct r_hlsl_permutation_s *hashnext;
5794         unsigned int mode;
5795         unsigned int permutation;
5796
5797         /// indicates if we have tried compiling this permutation already
5798         qboolean compiled;
5799         /// NULL if compilation failed
5800         IDirect3DVertexShader9 *vertexshader;
5801         IDirect3DPixelShader9 *pixelshader;
5802 }
5803 r_hlsl_permutation_t;
5804
5805 typedef enum D3DVSREGISTER_e
5806 {
5807         D3DVSREGISTER_TexMatrix = 0, // float4x4
5808         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
5809         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
5810         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
5811         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
5812         D3DVSREGISTER_ModelToLight = 20, // float4x4
5813         D3DVSREGISTER_EyePosition = 24,
5814         D3DVSREGISTER_FogPlane = 25,
5815         D3DVSREGISTER_LightDir = 26,
5816         D3DVSREGISTER_LightPosition = 27,
5817 }
5818 D3DVSREGISTER_t;
5819
5820 typedef enum D3DPSREGISTER_e
5821 {
5822         D3DPSREGISTER_Alpha = 0,
5823         D3DPSREGISTER_BloomBlur_Parameters = 1,
5824         D3DPSREGISTER_ClientTime = 2,
5825         D3DPSREGISTER_Color_Ambient = 3,
5826         D3DPSREGISTER_Color_Diffuse = 4,
5827         D3DPSREGISTER_Color_Specular = 5,
5828         D3DPSREGISTER_Color_Glow = 6,
5829         D3DPSREGISTER_Color_Pants = 7,
5830         D3DPSREGISTER_Color_Shirt = 8,
5831         D3DPSREGISTER_DeferredColor_Ambient = 9,
5832         D3DPSREGISTER_DeferredColor_Diffuse = 10,
5833         D3DPSREGISTER_DeferredColor_Specular = 11,
5834         D3DPSREGISTER_DeferredMod_Diffuse = 12,
5835         D3DPSREGISTER_DeferredMod_Specular = 13,
5836         D3DPSREGISTER_DistortScaleRefractReflect = 14,
5837         D3DPSREGISTER_EyePosition = 15, // unused
5838         D3DPSREGISTER_FogColor = 16,
5839         D3DPSREGISTER_FogHeightFade = 17,
5840         D3DPSREGISTER_FogPlane = 18,
5841         D3DPSREGISTER_FogPlaneViewDist = 19,
5842         D3DPSREGISTER_FogRangeRecip = 20,
5843         D3DPSREGISTER_LightColor = 21,
5844         D3DPSREGISTER_LightDir = 22, // unused
5845         D3DPSREGISTER_LightPosition = 23,
5846         D3DPSREGISTER_OffsetMapping_Scale = 24,
5847         D3DPSREGISTER_PixelSize = 25,
5848         D3DPSREGISTER_ReflectColor = 26,
5849         D3DPSREGISTER_ReflectFactor = 27,
5850         D3DPSREGISTER_ReflectOffset = 28,
5851         D3DPSREGISTER_RefractColor = 29,
5852         D3DPSREGISTER_Saturation = 30,
5853         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
5854         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
5855         D3DPSREGISTER_ScreenToDepth = 33,
5856         D3DPSREGISTER_ShadowMap_Parameters = 34,
5857         D3DPSREGISTER_ShadowMap_TextureScale = 35,
5858         D3DPSREGISTER_SpecularPower = 36,
5859         D3DPSREGISTER_UserVec1 = 37,
5860         D3DPSREGISTER_UserVec2 = 38,
5861         D3DPSREGISTER_UserVec3 = 39,
5862         D3DPSREGISTER_UserVec4 = 40,
5863         D3DPSREGISTER_ViewTintColor = 41,
5864         D3DPSREGISTER_PixelToScreenTexCoord = 42,
5865         D3DPSREGISTER_BloomColorSubtract = 43,
5866         D3DPSREGISTER_ViewToLight = 44, // float4x4
5867         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
5868         D3DPSREGISTER_NormalmapScrollBlend = 52,
5869         // next at 53
5870 }
5871 D3DPSREGISTER_t;
5872
5873 /// information about each possible shader permutation
5874 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
5875 /// currently selected permutation
5876 r_hlsl_permutation_t *r_hlsl_permutation;
5877 /// storage for permutations linked in the hash table
5878 memexpandablearray_t r_hlsl_permutationarray;
5879
5880 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
5881 {
5882         //unsigned int hashdepth = 0;
5883         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
5884         r_hlsl_permutation_t *p;
5885         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
5886         {
5887                 if (p->mode == mode && p->permutation == permutation)
5888                 {
5889                         //if (hashdepth > 10)
5890                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
5891                         return p;
5892                 }
5893                 //hashdepth++;
5894         }
5895         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
5896         p->mode = mode;
5897         p->permutation = permutation;
5898         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
5899         r_hlsl_permutationhash[mode][hashindex] = p;
5900         //if (hashdepth > 10)
5901         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
5902         return p;
5903 }
5904
5905 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
5906 {
5907         char *shaderstring;
5908         if (!filename || !filename[0])
5909                 return NULL;
5910         if (!strcmp(filename, "hlsl/default.hlsl"))
5911         {
5912                 if (!hlslshaderstring)
5913                 {
5914                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
5915                         if (hlslshaderstring)
5916                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
5917                         else
5918                                 hlslshaderstring = (char *)builtincgshaderstring;
5919                 }
5920                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
5921                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
5922                 return shaderstring;
5923         }
5924         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
5925         if (shaderstring)
5926         {
5927                 if (printfromdisknotice)
5928                         Con_DPrintf("from disk %s... ", filename);
5929                 return shaderstring;
5930         }
5931         return shaderstring;
5932 }
5933
5934 #include <d3dx9.h>
5935 //#include <d3dx9shader.h>
5936 //#include <d3dx9mesh.h>
5937
5938 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
5939 {
5940         DWORD *vsbin = NULL;
5941         DWORD *psbin = NULL;
5942         fs_offset_t vsbinsize;
5943         fs_offset_t psbinsize;
5944 //      IDirect3DVertexShader9 *vs = NULL;
5945 //      IDirect3DPixelShader9 *ps = NULL;
5946         ID3DXBuffer *vslog = NULL;
5947         ID3DXBuffer *vsbuffer = NULL;
5948         ID3DXConstantTable *vsconstanttable = NULL;
5949         ID3DXBuffer *pslog = NULL;
5950         ID3DXBuffer *psbuffer = NULL;
5951         ID3DXConstantTable *psconstanttable = NULL;
5952         int vsresult = 0;
5953         int psresult = 0;
5954         char temp[MAX_INPUTLINE];
5955         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
5956         qboolean debugshader = gl_paranoid.integer != 0;
5957         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
5958         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
5959         if (!debugshader)
5960         {
5961                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
5962                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
5963         }
5964         if ((!vsbin && vertstring) || (!psbin && fragstring))
5965         {
5966                 const char* dllnames_d3dx9 [] =
5967                 {
5968                         "d3dx9_43.dll",
5969                         "d3dx9_42.dll",
5970                         "d3dx9_41.dll",
5971                         "d3dx9_40.dll",
5972                         "d3dx9_39.dll",
5973                         "d3dx9_38.dll",
5974                         "d3dx9_37.dll",
5975                         "d3dx9_36.dll",
5976                         "d3dx9_35.dll",
5977                         "d3dx9_34.dll",
5978                         "d3dx9_33.dll",
5979                         "d3dx9_32.dll",
5980                         "d3dx9_31.dll",
5981                         "d3dx9_30.dll",
5982                         "d3dx9_29.dll",
5983                         "d3dx9_28.dll",
5984                         "d3dx9_27.dll",
5985                         "d3dx9_26.dll",
5986                         "d3dx9_25.dll",
5987                         "d3dx9_24.dll",
5988                         NULL
5989                 };
5990                 dllhandle_t d3dx9_dll = NULL;
5991                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
5992                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
5993                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
5994                 dllfunction_t d3dx9_dllfuncs[] =
5995                 {
5996                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
5997                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
5998                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
5999                         {NULL, NULL}
6000                 };
6001                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
6002                 {
6003                         DWORD shaderflags = 0;
6004                         if (debugshader)
6005                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
6006                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
6007                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
6008                         if (vertstring && vertstring[0])
6009                         {
6010                                 if (debugshader)
6011                                 {
6012 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
6013 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
6014                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
6015                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
6016                                 }
6017                                 else
6018                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
6019                                 if (vsbuffer)
6020                                 {
6021                                         vsbinsize = vsbuffer->GetBufferSize();
6022                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
6023                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
6024                                         vsbuffer->Release();
6025                                 }
6026                                 if (vslog)
6027                                 {
6028                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
6029                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
6030                                         vslog->Release();
6031                                 }
6032                         }
6033                         if (fragstring && fragstring[0])
6034                         {
6035                                 if (debugshader)
6036                                 {
6037 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
6038 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
6039                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
6040                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
6041                                 }
6042                                 else
6043                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
6044                                 if (psbuffer)
6045                                 {
6046                                         psbinsize = psbuffer->GetBufferSize();
6047                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
6048                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
6049                                         psbuffer->Release();
6050                                 }
6051                                 if (pslog)
6052                                 {
6053                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
6054                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
6055                                         pslog->Release();
6056                                 }
6057                         }
6058                         Sys_UnloadLibrary(&d3dx9_dll);
6059                 }
6060                 else
6061                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
6062         }
6063         if (vsbin && psbin)
6064         {
6065                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
6066                 if (FAILED(vsresult))
6067                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
6068                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
6069                 if (FAILED(psresult))
6070                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
6071         }
6072         // free the shader data
6073         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
6074         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
6075 }
6076
6077 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
6078 {
6079         int i;
6080         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
6081         int vertstring_length = 0;
6082         int geomstring_length = 0;
6083         int fragstring_length = 0;
6084         char *t;
6085         char *vertexstring, *geometrystring, *fragmentstring;
6086         char *vertstring, *geomstring, *fragstring;
6087         char permutationname[256];
6088         char cachename[256];
6089         int vertstrings_count = 0;
6090         int geomstrings_count = 0;
6091         int fragstrings_count = 0;
6092         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
6093         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
6094         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
6095
6096         if (p->compiled)
6097                 return;
6098         p->compiled = true;
6099         p->vertexshader = NULL;
6100         p->pixelshader = NULL;
6101
6102         permutationname[0] = 0;
6103         cachename[0] = 0;
6104         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
6105         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
6106         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
6107
6108         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
6109         strlcat(cachename, "hlsl/", sizeof(cachename));
6110
6111         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
6112         vertstrings_count = 0;
6113         geomstrings_count = 0;
6114         fragstrings_count = 0;
6115         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
6116         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
6117         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
6118
6119         // the first pretext is which type of shader to compile as
6120         // (later these will all be bound together as a program object)
6121         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
6122         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
6123         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
6124
6125         // the second pretext is the mode (for example a light source)
6126         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
6127         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
6128         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
6129         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
6130         strlcat(cachename, modeinfo->name, sizeof(cachename));
6131
6132         // now add all the permutation pretexts
6133         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
6134         {
6135                 if (permutation & (1<<i))
6136                 {
6137                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
6138                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
6139                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
6140                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
6141                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
6142                 }
6143                 else
6144                 {
6145                         // keep line numbers correct
6146                         vertstrings_list[vertstrings_count++] = "\n";
6147                         geomstrings_list[geomstrings_count++] = "\n";
6148                         fragstrings_list[fragstrings_count++] = "\n";
6149                 }
6150         }
6151
6152         // add static parms
6153         R_CompileShader_AddStaticParms(mode, permutation);
6154         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
6155         vertstrings_count += shaderstaticparms_count;
6156         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
6157         geomstrings_count += shaderstaticparms_count;
6158         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
6159         fragstrings_count += shaderstaticparms_count;
6160
6161         // replace spaces in the cachename with _ characters
6162         for (i = 0;cachename[i];i++)
6163                 if (cachename[i] == ' ')
6164                         cachename[i] = '_';
6165
6166         // now append the shader text itself
6167         vertstrings_list[vertstrings_count++] = vertexstring;
6168         geomstrings_list[geomstrings_count++] = geometrystring;
6169         fragstrings_list[fragstrings_count++] = fragmentstring;
6170
6171         // if any sources were NULL, clear the respective list
6172         if (!vertexstring)
6173                 vertstrings_count = 0;
6174         if (!geometrystring)
6175                 geomstrings_count = 0;
6176         if (!fragmentstring)
6177                 fragstrings_count = 0;
6178
6179         vertstring_length = 0;
6180         for (i = 0;i < vertstrings_count;i++)
6181                 vertstring_length += strlen(vertstrings_list[i]);
6182         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
6183         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
6184                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
6185
6186         geomstring_length = 0;
6187         for (i = 0;i < geomstrings_count;i++)
6188                 geomstring_length += strlen(geomstrings_list[i]);
6189         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
6190         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
6191                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
6192
6193         fragstring_length = 0;
6194         for (i = 0;i < fragstrings_count;i++)
6195                 fragstring_length += strlen(fragstrings_list[i]);
6196         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
6197         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
6198                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
6199
6200         // try to load the cached shader, or generate one
6201         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
6202
6203         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
6204                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
6205         else
6206                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
6207
6208         // free the strings
6209         if (vertstring)
6210                 Mem_Free(vertstring);
6211         if (geomstring)
6212                 Mem_Free(geomstring);
6213         if (fragstring)
6214                 Mem_Free(fragstring);
6215         if (vertexstring)
6216                 Mem_Free(vertexstring);
6217         if (geometrystring)
6218                 Mem_Free(geometrystring);
6219         if (fragmentstring)
6220                 Mem_Free(fragmentstring);
6221 }
6222
6223 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
6224 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
6225 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);}
6226 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);}
6227 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);}
6228 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);}
6229
6230 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
6231 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
6232 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);}
6233 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);}
6234 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);}
6235 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);}
6236
6237 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
6238 {
6239         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
6240         if (r_hlsl_permutation != perm)
6241         {
6242                 r_hlsl_permutation = perm;
6243                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
6244                 {
6245                         if (!r_hlsl_permutation->compiled)
6246                                 R_HLSL_CompilePermutation(perm, mode, permutation);
6247                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
6248                         {
6249                                 // remove features until we find a valid permutation
6250                                 int i;
6251                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
6252                                 {
6253                                         // reduce i more quickly whenever it would not remove any bits
6254                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
6255                                         if (!(permutation & j))
6256                                                 continue;
6257                                         permutation -= j;
6258                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
6259                                         if (!r_hlsl_permutation->compiled)
6260                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
6261                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
6262                                                 break;
6263                                 }
6264                                 if (i >= SHADERPERMUTATION_COUNT)
6265                                 {
6266                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
6267                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
6268                                         return; // no bit left to clear, entire mode is broken
6269                                 }
6270                         }
6271                 }
6272                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
6273                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
6274         }
6275         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
6276         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
6277         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
6278 }
6279 #endif
6280
6281 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
6282 {
6283         DPSOFTRAST_SetShader(mode, permutation);
6284         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
6285         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
6286         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
6287 }
6288
6289 void R_GLSL_Restart_f(void)
6290 {
6291         unsigned int i, limit;
6292         if (glslshaderstring && glslshaderstring != builtinshaderstring && glslshaderstring != builtingles2shaderstring)
6293                 Mem_Free(glslshaderstring);
6294         glslshaderstring = NULL;
6295         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
6296                 Mem_Free(cgshaderstring);
6297         cgshaderstring = NULL;
6298         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
6299                 Mem_Free(hlslshaderstring);
6300         hlslshaderstring = NULL;
6301         switch(vid.renderpath)
6302         {
6303         case RENDERPATH_D3D9:
6304 #ifdef SUPPORTD3D
6305                 {
6306                         r_hlsl_permutation_t *p;
6307                         r_hlsl_permutation = NULL;
6308 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
6309 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
6310 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
6311 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
6312                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
6313                         for (i = 0;i < limit;i++)
6314                         {
6315                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
6316                                 {
6317                                         if (p->vertexshader)
6318                                                 IDirect3DVertexShader9_Release(p->vertexshader);
6319                                         if (p->pixelshader)
6320                                                 IDirect3DPixelShader9_Release(p->pixelshader);
6321                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
6322                                 }
6323                         }
6324                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6325                 }
6326 #endif
6327                 break;
6328         case RENDERPATH_D3D10:
6329                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6330                 break;
6331         case RENDERPATH_D3D11:
6332                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6333                 break;
6334         case RENDERPATH_GL20:
6335         case RENDERPATH_GLES2:
6336                 {
6337                         r_glsl_permutation_t *p;
6338                         r_glsl_permutation = NULL;
6339                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
6340                         for (i = 0;i < limit;i++)
6341                         {
6342                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
6343                                 {
6344                                         GL_Backend_FreeProgram(p->program);
6345                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
6346                                 }
6347                         }
6348                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6349                 }
6350                 break;
6351         case RENDERPATH_CGGL:
6352 #ifdef SUPPORTCG
6353                 {
6354                         r_cg_permutation_t *p;
6355                         r_cg_permutation = NULL;
6356                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
6357                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
6358                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
6359                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
6360                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
6361                         for (i = 0;i < limit;i++)
6362                         {
6363                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
6364                                 {
6365                                         if (p->vprogram)
6366                                                 cgDestroyProgram(p->vprogram);
6367                                         if (p->fprogram)
6368                                                 cgDestroyProgram(p->fprogram);
6369                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
6370                                 }
6371                         }
6372                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6373                 }
6374 #endif
6375                 break;
6376         case RENDERPATH_GL13:
6377         case RENDERPATH_GL11:
6378                 break;
6379         case RENDERPATH_SOFT:
6380                 break;
6381         }
6382 }
6383
6384 void R_GLSL_DumpShader_f(void)
6385 {
6386         int i;
6387         qfile_t *file;
6388
6389         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
6390         if (file)
6391         {
6392                 FS_Print(file, "/* The engine may define the following macros:\n");
6393                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
6394                 for (i = 0;i < SHADERMODE_COUNT;i++)
6395                         FS_Print(file, glslshadermodeinfo[i].pretext);
6396                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
6397                         FS_Print(file, shaderpermutationinfo[i].pretext);
6398                 FS_Print(file, "*/\n");
6399                 FS_Print(file, builtinshaderstring);
6400                 FS_Close(file);
6401                 Con_Printf("glsl/default.glsl written\n");
6402         }
6403         else
6404                 Con_Printf("failed to write to glsl/default.glsl\n");
6405
6406         file = FS_OpenRealFile("gles2/default.glsl", "w", false);
6407         if (file)
6408         {
6409                 FS_Print(file, "/* The engine may define the following macros:\n");
6410                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
6411                 for (i = 0;i < SHADERMODE_COUNT;i++)
6412                         FS_Print(file, glslshadermodeinfo[i].pretext);
6413                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
6414                         FS_Print(file, shaderpermutationinfo[i].pretext);
6415                 FS_Print(file, "*/\n");
6416                 FS_Print(file, builtingles2shaderstring);
6417                 FS_Close(file);
6418                 Con_Printf("gles2/default.glsl written\n");
6419         }
6420         else
6421                 Con_Printf("failed to write to glsl/default.glsl\n");
6422
6423 #ifdef SUPPORTCG
6424         file = FS_OpenRealFile("cg/default.cg", "w", false);
6425         if (file)
6426         {
6427                 FS_Print(file, "/* The engine may define the following macros:\n");
6428                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
6429                 for (i = 0;i < SHADERMODE_COUNT;i++)
6430                         FS_Print(file, cgshadermodeinfo[i].pretext);
6431                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
6432                         FS_Print(file, shaderpermutationinfo[i].pretext);
6433                 FS_Print(file, "*/\n");
6434                 FS_Print(file, builtincgshaderstring);
6435                 FS_Close(file);
6436                 Con_Printf("cg/default.cg written\n");
6437         }
6438         else
6439                 Con_Printf("failed to write to cg/default.cg\n");
6440 #endif
6441
6442         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
6443         if (file)
6444         {
6445                 FS_Print(file, "/* The engine may define the following macros:\n");
6446                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
6447                 for (i = 0;i < SHADERMODE_COUNT;i++)
6448                         FS_Print(file, hlslshadermodeinfo[i].pretext);
6449                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
6450                         FS_Print(file, shaderpermutationinfo[i].pretext);
6451                 FS_Print(file, "*/\n");
6452                 FS_Print(file, builtincgshaderstring);
6453                 FS_Close(file);
6454                 Con_Printf("hlsl/default.hlsl written\n");
6455         }
6456         else
6457                 Con_Printf("failed to write to hlsl/default.hlsl\n");
6458 }
6459
6460 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
6461 {
6462         if (!second)
6463                 texturemode = GL_MODULATE;
6464         switch (vid.renderpath)
6465         {
6466         case RENDERPATH_D3D9:
6467 #ifdef SUPPORTD3D
6468                 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))));
6469                 R_Mesh_TexBind(GL20TU_FIRST , first );
6470                 R_Mesh_TexBind(GL20TU_SECOND, second);
6471 #endif
6472                 break;
6473         case RENDERPATH_D3D10:
6474                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6475                 break;
6476         case RENDERPATH_D3D11:
6477                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6478                 break;
6479         case RENDERPATH_GL20:
6480         case RENDERPATH_GLES2:
6481                 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))));
6482                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
6483                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
6484                 break;
6485         case RENDERPATH_CGGL:
6486 #ifdef SUPPORTCG
6487                 CHECKCGERROR
6488                 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))));
6489                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
6490                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
6491 #endif
6492                 break;
6493         case RENDERPATH_GL13:
6494                 R_Mesh_TexBind(0, first );
6495                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
6496                 R_Mesh_TexBind(1, second);
6497                 if (second)
6498                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
6499                 break;
6500         case RENDERPATH_GL11:
6501                 R_Mesh_TexBind(0, first );
6502                 break;
6503         case RENDERPATH_SOFT:
6504                 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))));
6505                 R_Mesh_TexBind(GL20TU_FIRST , first );
6506                 R_Mesh_TexBind(GL20TU_SECOND, second);
6507                 break;
6508         }
6509 }
6510
6511 void R_SetupShader_DepthOrShadow(void)
6512 {
6513         switch (vid.renderpath)
6514         {
6515         case RENDERPATH_D3D9:
6516 #ifdef SUPPORTD3D
6517                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
6518 #endif
6519                 break;
6520         case RENDERPATH_D3D10:
6521                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6522                 break;
6523         case RENDERPATH_D3D11:
6524                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6525                 break;
6526         case RENDERPATH_GL20:
6527         case RENDERPATH_GLES2:
6528                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
6529                 break;
6530         case RENDERPATH_CGGL:
6531 #ifdef SUPPORTCG
6532                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
6533 #endif
6534                 break;
6535         case RENDERPATH_GL13:
6536                 R_Mesh_TexBind(0, 0);
6537                 R_Mesh_TexBind(1, 0);
6538                 break;
6539         case RENDERPATH_GL11:
6540                 R_Mesh_TexBind(0, 0);
6541                 break;
6542         case RENDERPATH_SOFT:
6543                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
6544                 break;
6545         }
6546 }
6547
6548 void R_SetupShader_ShowDepth(void)
6549 {
6550         switch (vid.renderpath)
6551         {
6552         case RENDERPATH_D3D9:
6553 #ifdef SUPPORTHLSL
6554                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
6555 #endif
6556                 break;
6557         case RENDERPATH_D3D10:
6558                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6559                 break;
6560         case RENDERPATH_D3D11:
6561                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6562                 break;
6563         case RENDERPATH_GL20:
6564         case RENDERPATH_GLES2:
6565                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
6566                 break;
6567         case RENDERPATH_CGGL:
6568 #ifdef SUPPORTCG
6569                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
6570 #endif
6571                 break;
6572         case RENDERPATH_GL13:
6573                 break;
6574         case RENDERPATH_GL11:
6575                 break;
6576         case RENDERPATH_SOFT:
6577                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
6578                 break;
6579         }
6580 }
6581
6582 extern qboolean r_shadow_usingdeferredprepass;
6583 extern cvar_t r_shadow_deferred_8bitrange;
6584 extern rtexture_t *r_shadow_attenuationgradienttexture;
6585 extern rtexture_t *r_shadow_attenuation2dtexture;
6586 extern rtexture_t *r_shadow_attenuation3dtexture;
6587 extern qboolean r_shadow_usingshadowmap2d;
6588 extern qboolean r_shadow_usingshadowmaportho;
6589 extern float r_shadow_shadowmap_texturescale[2];
6590 extern float r_shadow_shadowmap_parameters[4];
6591 extern qboolean r_shadow_shadowmapvsdct;
6592 extern qboolean r_shadow_shadowmapsampler;
6593 extern int r_shadow_shadowmappcf;
6594 extern rtexture_t *r_shadow_shadowmap2dtexture;
6595 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
6596 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
6597 extern matrix4x4_t r_shadow_shadowmapmatrix;
6598 extern int r_shadow_shadowmaplod; // changes for each light based on distance
6599 extern int r_shadow_prepass_width;
6600 extern int r_shadow_prepass_height;
6601 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
6602 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
6603 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
6604 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
6605 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
6606 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
6607 {
6608         // a blendfunc allows colormod if:
6609         // a) it can never keep the destination pixel invariant, or
6610         // b) it can keep the destination pixel invariant, and still can do so if colormodded
6611         // this is to prevent unintended side effects from colormod
6612
6613         // in formulas:
6614         // IF there is a (s, sa) for which for all (d, da),
6615         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
6616         // THEN, for this (s, sa) and all (colormod, d, da):
6617         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
6618         // OBVIOUSLY, this means that
6619         //   s*colormod * src(s*colormod, d, sa, da) = 0
6620         //   dst(s*colormod, d, sa, da)              = 1
6621
6622         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
6623
6624         // main condition to leave dst color invariant:
6625         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
6626         //   src == GL_ZERO:
6627         //     s * 0 + d * dst(s, d, sa, da) == d
6628         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
6629         //       => colormod is a problem for GL_SRC_COLOR only
6630         //   src == GL_ONE:
6631         //     s + d * dst(s, d, sa, da) == d
6632         //       => s == 0
6633         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
6634         //       => colormod is never problematic for these
6635         //   src == GL_SRC_COLOR:
6636         //     s*s + d * dst(s, d, sa, da) == d
6637         //       => s == 0
6638         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
6639         //       => colormod is never problematic for these
6640         //   src == GL_ONE_MINUS_SRC_COLOR:
6641         //     s*(1-s) + d * dst(s, d, sa, da) == d
6642         //       => s == 0 or s == 1
6643         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
6644         //       => colormod is a problem for GL_SRC_COLOR only
6645         //   src == GL_DST_COLOR
6646         //     s*d + d * dst(s, d, sa, da) == d
6647         //       => s == 1
6648         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
6649         //       => colormod is always a problem
6650         //     or
6651         //       => s == 0
6652         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
6653         //       => colormod is never problematic for these
6654         //       => BUT, we do not know s! We must assume it is problematic
6655         //       then... except in GL_ONE case, where we know all invariant
6656         //       cases are fine
6657         //   src == GL_ONE_MINUS_DST_COLOR
6658         //     s*(1-d) + d * dst(s, d, sa, da) == d
6659         //       => s == 0 (1-d is impossible to handle for our desired result)
6660         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
6661         //       => colormod is never problematic for these
6662         //   src == GL_SRC_ALPHA
6663         //     s*sa + d * dst(s, d, sa, da) == d
6664         //       => s == 0, or sa == 0
6665         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
6666         //       => colormod breaks in the case GL_SRC_COLOR only
6667         //   src == GL_ONE_MINUS_SRC_ALPHA
6668         //     s*(1-sa) + d * dst(s, d, sa, da) == d
6669         //       => s == 0, or sa == 1
6670         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
6671         //       => colormod breaks in the case GL_SRC_COLOR only
6672         //   src == GL_DST_ALPHA
6673         //     s*da + d * dst(s, d, sa, da) == d
6674         //       => s == 0
6675         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
6676         //       => colormod is never problematic for these
6677
6678         switch(src)
6679         {
6680                 case GL_ZERO:
6681                 case GL_ONE_MINUS_SRC_COLOR:
6682                 case GL_SRC_ALPHA:
6683                 case GL_ONE_MINUS_SRC_ALPHA:
6684                         if(dst == GL_SRC_COLOR)
6685                                 return false;
6686                         return true;
6687                 case GL_ONE:
6688                 case GL_SRC_COLOR:
6689                 case GL_ONE_MINUS_DST_COLOR:
6690                 case GL_DST_ALPHA:
6691                 case GL_ONE_MINUS_DST_ALPHA:
6692                         return true;
6693                 case GL_DST_COLOR:
6694                         if(dst == GL_ONE)
6695                                 return true;
6696                         return false;
6697                 default:
6698                         return false;
6699         }
6700 }
6701 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)
6702 {
6703         // select a permutation of the lighting shader appropriate to this
6704         // combination of texture, entity, light source, and fogging, only use the
6705         // minimum features necessary to avoid wasting rendering time in the
6706         // fragment shader on features that are not being used
6707         unsigned int permutation = 0;
6708         unsigned int mode = 0;
6709         qboolean allow_colormod;
6710         static float dummy_colormod[3] = {1, 1, 1};
6711         float *colormod = rsurface.colormod;
6712         float m16f[16];
6713         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
6714         if (rsurfacepass == RSURFPASS_BACKGROUND)
6715         {
6716                 // distorted background
6717                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
6718                 {
6719                         mode = SHADERMODE_WATER;
6720                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
6721                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
6722                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
6723                         {
6724                                 // this is the right thing to do for wateralpha
6725                                 GL_BlendFunc(GL_ONE, GL_ZERO);
6726                                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
6727                         }
6728                         else
6729                         {
6730                                 // this is the right thing to do for entity alpha
6731                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6732                                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6733                         }
6734                 }
6735                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
6736                 {
6737                         mode = SHADERMODE_REFRACTION;
6738                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6739                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6740                 }
6741                 else
6742                 {
6743                         mode = SHADERMODE_GENERIC;
6744                         permutation |= SHADERPERMUTATION_DIFFUSE;
6745                         GL_BlendFunc(GL_ONE, GL_ZERO);
6746                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
6747                 }
6748                 GL_AlphaTest(false);
6749         }
6750         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
6751         {
6752                 if (r_glsl_offsetmapping.integer)
6753                 {
6754                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
6755                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
6756                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
6757                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
6758                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
6759                         {
6760                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
6761                                 if (r_glsl_offsetmapping_reliefmapping.integer)
6762                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
6763                         }
6764                 }
6765                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
6766                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
6767                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6768                         permutation |= SHADERPERMUTATION_ALPHAKILL;
6769                 // normalmap (deferred prepass), may use alpha test on diffuse
6770                 mode = SHADERMODE_DEFERREDGEOMETRY;
6771                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
6772                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
6773                 GL_AlphaTest(false);
6774                 GL_BlendFunc(GL_ONE, GL_ZERO);
6775                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
6776         }
6777         else if (rsurfacepass == RSURFPASS_RTLIGHT)
6778         {
6779                 if (r_glsl_offsetmapping.integer)
6780                 {
6781                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
6782                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
6783                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
6784                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
6785                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
6786                         {
6787                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
6788                                 if (r_glsl_offsetmapping_reliefmapping.integer)
6789                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
6790                         }
6791                 }
6792                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
6793                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
6794                 // light source
6795                 mode = SHADERMODE_LIGHTSOURCE;
6796                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
6797                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
6798                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
6799                         permutation |= SHADERPERMUTATION_CUBEFILTER;
6800                 if (diffusescale > 0)
6801                         permutation |= SHADERPERMUTATION_DIFFUSE;
6802                 if (specularscale > 0)
6803                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6804                 if (r_refdef.fogenabled)
6805                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
6806                 if (rsurface.texture->colormapping)
6807                         permutation |= SHADERPERMUTATION_COLORMAPPING;
6808                 if (r_shadow_usingshadowmap2d)
6809                 {
6810                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6811                         if(r_shadow_shadowmapvsdct)
6812                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6813
6814                         if (r_shadow_shadowmapsampler)
6815                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6816                         if (r_shadow_shadowmappcf > 1)
6817                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6818                         else if (r_shadow_shadowmappcf)
6819                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6820                 }
6821                 if (rsurface.texture->reflectmasktexture)
6822                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
6823                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6824                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6825                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
6826         }
6827         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6828         {
6829                 if (r_glsl_offsetmapping.integer)
6830                 {
6831                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
6832                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
6833                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
6834                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
6835                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
6836                         {
6837                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
6838                                 if (r_glsl_offsetmapping_reliefmapping.integer)
6839                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
6840                         }
6841                 }
6842                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
6843                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
6844                 // unshaded geometry (fullbright or ambient model lighting)
6845                 mode = SHADERMODE_FLATCOLOR;
6846                 ambientscale = diffusescale = specularscale = 0;
6847                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
6848                         permutation |= SHADERPERMUTATION_GLOW;
6849                 if (r_refdef.fogenabled)
6850                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
6851                 if (rsurface.texture->colormapping)
6852                         permutation |= SHADERPERMUTATION_COLORMAPPING;
6853                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
6854                 {
6855                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
6856                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6857
6858                         if (r_shadow_shadowmapsampler)
6859                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6860                         if (r_shadow_shadowmappcf > 1)
6861                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6862                         else if (r_shadow_shadowmappcf)
6863                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6864                 }
6865                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
6866                         permutation |= SHADERPERMUTATION_REFLECTION;
6867                 if (rsurface.texture->reflectmasktexture)
6868                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
6869                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6870                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6871                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6872         }
6873         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
6874         {
6875                 if (r_glsl_offsetmapping.integer)
6876                 {
6877                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
6878                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
6879                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
6880                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
6881                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
6882                         {
6883                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
6884                                 if (r_glsl_offsetmapping_reliefmapping.integer)
6885                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
6886                         }
6887                 }
6888                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
6889                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
6890                 // directional model lighting
6891                 mode = SHADERMODE_LIGHTDIRECTION;
6892                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
6893                         permutation |= SHADERPERMUTATION_GLOW;
6894                 permutation |= SHADERPERMUTATION_DIFFUSE;
6895                 if (specularscale > 0)
6896                         permutation |= SHADERPERMUTATION_SPECULAR;
6897                 if (r_refdef.fogenabled)
6898                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
6899                 if (rsurface.texture->colormapping)
6900                         permutation |= SHADERPERMUTATION_COLORMAPPING;
6901                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
6902                 {
6903                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
6904                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6905
6906                         if (r_shadow_shadowmapsampler)
6907                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6908                         if (r_shadow_shadowmappcf > 1)
6909                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6910                         else if (r_shadow_shadowmappcf)
6911                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6912                 }
6913                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
6914                         permutation |= SHADERPERMUTATION_REFLECTION;
6915                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
6916                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
6917                 if (rsurface.texture->reflectmasktexture)
6918                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
6919                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6920                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6921                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6922         }
6923         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6924         {
6925                 if (r_glsl_offsetmapping.integer)
6926                 {
6927                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
6928                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
6929                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
6930                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
6931                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
6932                         {
6933                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
6934                                 if (r_glsl_offsetmapping_reliefmapping.integer)
6935                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
6936                         }
6937                 }
6938                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
6939                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
6940                 // ambient model lighting
6941                 mode = SHADERMODE_LIGHTDIRECTION;
6942                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
6943                         permutation |= SHADERPERMUTATION_GLOW;
6944                 if (r_refdef.fogenabled)
6945                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
6946                 if (rsurface.texture->colormapping)
6947                         permutation |= SHADERPERMUTATION_COLORMAPPING;
6948                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
6949                 {
6950                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
6951                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6952
6953                         if (r_shadow_shadowmapsampler)
6954                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6955                         if (r_shadow_shadowmappcf > 1)
6956                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6957                         else if (r_shadow_shadowmappcf)
6958                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6959                 }
6960                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
6961                         permutation |= SHADERPERMUTATION_REFLECTION;
6962                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
6963                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
6964                 if (rsurface.texture->reflectmasktexture)
6965                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
6966                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6967                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6968                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6969         }
6970         else
6971         {
6972                 if (r_glsl_offsetmapping.integer)
6973                 {
6974                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
6975                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
6976                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
6977                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
6978                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
6979                         {
6980                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
6981                                 if (r_glsl_offsetmapping_reliefmapping.integer)
6982                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
6983                         }
6984                 }
6985                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
6986                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
6987                 // lightmapped wall
6988                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
6989                         permutation |= SHADERPERMUTATION_GLOW;
6990                 if (r_refdef.fogenabled)
6991                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
6992                 if (rsurface.texture->colormapping)
6993                         permutation |= SHADERPERMUTATION_COLORMAPPING;
6994                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
6995                 {
6996                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
6997                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6998
6999                         if (r_shadow_shadowmapsampler)
7000                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
7001                         if (r_shadow_shadowmappcf > 1)
7002                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
7003                         else if (r_shadow_shadowmappcf)
7004                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
7005                 }
7006                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
7007                         permutation |= SHADERPERMUTATION_REFLECTION;
7008                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
7009                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
7010                 if (rsurface.texture->reflectmasktexture)
7011                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
7012                 if (FAKELIGHT_ENABLED)
7013                 {
7014                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
7015                         mode = SHADERMODE_FAKELIGHT;
7016                         permutation |= SHADERPERMUTATION_DIFFUSE;
7017                         if (specularscale > 0)
7018                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
7019                 }
7020                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
7021                 {
7022                         // deluxemapping (light direction texture)
7023                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
7024                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
7025                         else
7026                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
7027                         permutation |= SHADERPERMUTATION_DIFFUSE;
7028                         if (specularscale > 0)
7029                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
7030                 }
7031                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
7032                 {
7033                         // fake deluxemapping (uniform light direction in tangentspace)
7034                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
7035                         permutation |= SHADERPERMUTATION_DIFFUSE;
7036                         if (specularscale > 0)
7037                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
7038                 }
7039                 else if (rsurface.uselightmaptexture)
7040                 {
7041                         // ordinary lightmapping (q1bsp, q3bsp)
7042                         mode = SHADERMODE_LIGHTMAP;
7043                 }
7044                 else
7045                 {
7046                         // ordinary vertex coloring (q3bsp)
7047                         mode = SHADERMODE_VERTEXCOLOR;
7048                 }
7049                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7050                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7051                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7052         }
7053         if(!allow_colormod)
7054                 colormod = dummy_colormod;
7055         switch(vid.renderpath)
7056         {
7057         case RENDERPATH_D3D9:
7058 #ifdef SUPPORTD3D
7059                 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);
7060                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
7061                 R_SetupShader_SetPermutationHLSL(mode, permutation);
7062                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
7063                 if (mode == SHADERMODE_LIGHTSOURCE)
7064                 {
7065                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
7066                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
7067                 }
7068                 else
7069                 {
7070                         if (mode == SHADERMODE_LIGHTDIRECTION)
7071                         {
7072                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
7073                         }
7074                 }
7075                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
7076                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
7077                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
7078                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
7079                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
7080
7081                 if (mode == SHADERMODE_LIGHTSOURCE)
7082                 {
7083                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
7084                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
7085                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
7086                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
7087                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
7088
7089                         // additive passes are only darkened by fog, not tinted
7090                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
7091                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
7092                 }
7093                 else
7094                 {
7095                         if (mode == SHADERMODE_FLATCOLOR)
7096                         {
7097                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
7098                         }
7099                         else if (mode == SHADERMODE_LIGHTDIRECTION)
7100                         {
7101                                 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]);
7102                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
7103                                 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);
7104                                 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);
7105                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
7106                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
7107                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
7108                         }
7109                         else
7110                         {
7111                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
7112                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
7113                                 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);
7114                                 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);
7115                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
7116                         }
7117                         // additive passes are only darkened by fog, not tinted
7118                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7119                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
7120                         else
7121                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
7122                         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);
7123                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
7124                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
7125                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
7126                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
7127                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
7128                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
7129                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
7130                         if (mode == SHADERMODE_WATER)
7131                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
7132                 }
7133                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
7134                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
7135                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
7136                 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));
7137                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
7138                 if (rsurface.texture->pantstexture)
7139                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
7140                 else
7141                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
7142                 if (rsurface.texture->shirttexture)
7143                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
7144                 else
7145                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
7146                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
7147                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
7148                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
7149                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
7150                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
7151                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
7152                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
7153
7154                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
7155                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
7156                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
7157                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
7158                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
7159                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
7160                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
7161                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
7162                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
7163                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
7164                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
7165                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
7166                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
7167                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
7168                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
7169                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
7170                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
7171                 if (rsurfacepass == RSURFPASS_BACKGROUND)
7172                 {
7173                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
7174                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
7175                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
7176                 }
7177                 else
7178                 {
7179                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
7180                 }
7181 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
7182 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
7183                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
7184                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
7185                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
7186                 {
7187                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
7188                         if (rsurface.rtlight)
7189                         {
7190                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
7191                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
7192                         }
7193                 }
7194 #endif
7195                 break;
7196         case RENDERPATH_D3D10:
7197                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7198                 break;
7199         case RENDERPATH_D3D11:
7200                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7201                 break;
7202         case RENDERPATH_GL20:
7203         case RENDERPATH_GLES2:
7204                 if (!vid.useinterleavedarrays)
7205                 {
7206                         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);
7207                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
7208                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
7209                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
7210                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
7211                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
7212                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
7213                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
7214                 }
7215                 else
7216                 {
7217                         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);
7218                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
7219                 }
7220                 R_SetupShader_SetPermutationGLSL(mode, permutation);
7221                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
7222                 if (mode == SHADERMODE_LIGHTSOURCE)
7223                 {
7224                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
7225                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
7226                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
7227                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
7228                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
7229                         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);
7230         
7231                         // additive passes are only darkened by fog, not tinted
7232                         if (r_glsl_permutation->loc_FogColor >= 0)
7233                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
7234                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
7235                 }
7236                 else
7237                 {
7238                         if (mode == SHADERMODE_FLATCOLOR)
7239                         {
7240                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
7241                         }
7242                         else if (mode == SHADERMODE_LIGHTDIRECTION)
7243                         {
7244                                 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]);
7245                                 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]);
7246                                 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);
7247                                 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);
7248                                 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);
7249                                 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]);
7250                                 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]);
7251                         }
7252                         else
7253                         {
7254                                 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]);
7255                                 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]);
7256                                 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);
7257                                 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);
7258                                 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);
7259                         }
7260                         // additive passes are only darkened by fog, not tinted
7261                         if (r_glsl_permutation->loc_FogColor >= 0)
7262                         {
7263                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7264                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
7265                                 else
7266                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
7267                         }
7268                         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);
7269                         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]);
7270                         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]);
7271                         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]);
7272                         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]);
7273                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
7274                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
7275                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
7276                         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]);
7277                 }
7278                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
7279                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
7280                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
7281                 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]);
7282                 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]);
7283
7284                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
7285                 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));
7286                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
7287                 if (r_glsl_permutation->loc_Color_Pants >= 0)
7288                 {
7289                         if (rsurface.texture->pantstexture)
7290                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
7291                         else
7292                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
7293                 }
7294                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
7295                 {
7296                         if (rsurface.texture->shirttexture)
7297                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
7298                         else
7299                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
7300                 }
7301                 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]);
7302                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
7303                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
7304                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
7305                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
7306                 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]);
7307                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7308
7309                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
7310                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
7311                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
7312                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
7313                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
7314                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
7315                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
7316                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
7317                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
7318                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
7319                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
7320                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
7321                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
7322                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
7323                 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);
7324                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
7325                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
7326                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
7327                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
7328                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
7329                 if (rsurfacepass == RSURFPASS_BACKGROUND)
7330                 {
7331                         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);
7332                         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);
7333                         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);
7334                 }
7335                 else
7336                 {
7337                         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);
7338                 }
7339                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
7340                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
7341                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
7342                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
7343                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
7344                 {
7345                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
7346                         if (rsurface.rtlight)
7347                         {
7348                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
7349                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
7350                         }
7351                 }
7352                 CHECKGLERROR
7353                 break;
7354         case RENDERPATH_CGGL:
7355 #ifdef SUPPORTCG
7356                 if (!vid.useinterleavedarrays)
7357                 {
7358                         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);
7359                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
7360                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
7361                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
7362                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
7363                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
7364                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
7365                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
7366                 }
7367                 else
7368                 {
7369                         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);
7370                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
7371                 }
7372                 R_SetupShader_SetPermutationCG(mode, permutation);
7373                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
7374                 if (mode == SHADERMODE_LIGHTSOURCE)
7375                 {
7376                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
7377                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
7378                 }
7379                 else
7380                 {
7381                         if (mode == SHADERMODE_LIGHTDIRECTION)
7382                         {
7383                                 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
7384                         }
7385                 }
7386                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
7387                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
7388                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
7389                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
7390                 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
7391                 CHECKGLERROR
7392
7393                 if (mode == SHADERMODE_LIGHTSOURCE)
7394                 {
7395                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
7396                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
7397                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
7398                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
7399                         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
7400
7401                         // additive passes are only darkened by fog, not tinted
7402                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
7403                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
7404                 }
7405                 else
7406                 {
7407                         if (mode == SHADERMODE_FLATCOLOR)
7408                         {
7409                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
7410                         }
7411                         else if (mode == SHADERMODE_LIGHTDIRECTION)
7412                         {
7413                                 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
7414                                 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
7415                                 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
7416                                 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
7417                                 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
7418                                 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
7419                                 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
7420                         }
7421                         else
7422                         {
7423                                 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
7424                                 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
7425                                 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
7426                                 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
7427                                 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
7428                         }
7429                         // additive passes are only darkened by fog, not tinted
7430                         if (r_cg_permutation->fp_FogColor)
7431                         {
7432                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7433                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
7434                                 else
7435                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
7436                                 CHECKCGERROR
7437                         }
7438                         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
7439                         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
7440                         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
7441                         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
7442                         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
7443                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
7444                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
7445                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
7446                         if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
7447                 }
7448                 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
7449                 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
7450                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
7451                 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
7452                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
7453                 if (r_cg_permutation->fp_Color_Pants)
7454                 {
7455                         if (rsurface.texture->pantstexture)
7456                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
7457                         else
7458                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
7459                         CHECKCGERROR
7460                 }
7461                 if (r_cg_permutation->fp_Color_Shirt)
7462                 {
7463                         if (rsurface.texture->shirttexture)
7464                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
7465                         else
7466                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
7467                         CHECKCGERROR
7468                 }
7469                 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
7470                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
7471                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
7472                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
7473                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
7474                 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
7475                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7476
7477         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
7478         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
7479         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
7480                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
7481                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
7482                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
7483                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
7484                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
7485                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
7486                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
7487                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
7488                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
7489                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
7490                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
7491                 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
7492                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
7493                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
7494                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
7495                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
7496                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
7497                 if (rsurfacepass == RSURFPASS_BACKGROUND)
7498                 {
7499                         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
7500                         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
7501                         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
7502                 }
7503                 else
7504                 {
7505                         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
7506                 }
7507                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
7508                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
7509                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
7510                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
7511                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
7512                 {
7513                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
7514                         if (rsurface.rtlight)
7515                         {
7516                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
7517                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
7518                         }
7519                 }
7520
7521                 CHECKGLERROR
7522 #endif
7523                 break;
7524         case RENDERPATH_GL13:
7525         case RENDERPATH_GL11:
7526                 break;
7527         case RENDERPATH_SOFT:
7528                 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);
7529                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
7530                 R_SetupShader_SetPermutationSoft(mode, permutation);
7531                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
7532                 if (mode == SHADERMODE_LIGHTSOURCE)
7533                 {
7534                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
7535                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
7536                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
7537                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
7538                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
7539                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
7540         
7541                         // additive passes are only darkened by fog, not tinted
7542                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
7543                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
7544                 }
7545                 else
7546                 {
7547                         if (mode == SHADERMODE_FLATCOLOR)
7548                         {
7549                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
7550                         }
7551                         else if (mode == SHADERMODE_LIGHTDIRECTION)
7552                         {
7553                                 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]);
7554                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
7555                                 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);
7556                                 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);
7557                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
7558                                 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]);
7559                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
7560                         }
7561                         else
7562                         {
7563                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
7564                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
7565                                 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);
7566                                 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);
7567                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
7568                         }
7569                         // additive passes are only darkened by fog, not tinted
7570                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7571                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
7572                         else
7573                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
7574                         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);
7575                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
7576                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
7577                         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]);
7578                         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]);
7579                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
7580                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
7581                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
7582                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
7583                 }
7584                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
7585                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
7586                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
7587                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
7588                 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]);
7589
7590                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
7591                 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));
7592                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
7593                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
7594                 {
7595                         if (rsurface.texture->pantstexture)
7596                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
7597                         else
7598                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
7599                 }
7600                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
7601                 {
7602                         if (rsurface.texture->shirttexture)
7603                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
7604                         else
7605                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
7606                 }
7607                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
7608                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
7609                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
7610                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
7611                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
7612                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
7613                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7614
7615                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
7616                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
7617                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
7618                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
7619                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
7620                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
7621                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
7622                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
7623                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
7624                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
7625                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
7626                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
7627                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
7628                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
7629                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
7630                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
7631                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
7632                 if (rsurfacepass == RSURFPASS_BACKGROUND)
7633                 {
7634                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
7635                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
7636                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
7637                 }
7638                 else
7639                 {
7640                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
7641                 }
7642 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
7643 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
7644                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
7645                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
7646                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
7647                 {
7648                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
7649                         if (rsurface.rtlight)
7650                         {
7651                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
7652                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
7653                         }
7654                 }
7655                 break;
7656         }
7657 }
7658
7659 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
7660 {
7661         // select a permutation of the lighting shader appropriate to this
7662         // combination of texture, entity, light source, and fogging, only use the
7663         // minimum features necessary to avoid wasting rendering time in the
7664         // fragment shader on features that are not being used
7665         unsigned int permutation = 0;
7666         unsigned int mode = 0;
7667         const float *lightcolorbase = rtlight->currentcolor;
7668         float ambientscale = rtlight->ambientscale;
7669         float diffusescale = rtlight->diffusescale;
7670         float specularscale = rtlight->specularscale;
7671         // this is the location of the light in view space
7672         vec3_t viewlightorigin;
7673         // this transforms from view space (camera) to light space (cubemap)
7674         matrix4x4_t viewtolight;
7675         matrix4x4_t lighttoview;
7676         float viewtolight16f[16];
7677         float range = 1.0f / r_shadow_deferred_8bitrange.value;
7678         // light source
7679         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
7680         if (rtlight->currentcubemap != r_texture_whitecube)
7681                 permutation |= SHADERPERMUTATION_CUBEFILTER;
7682         if (diffusescale > 0)
7683                 permutation |= SHADERPERMUTATION_DIFFUSE;
7684         if (specularscale > 0)
7685                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
7686         if (r_shadow_usingshadowmap2d)
7687         {
7688                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
7689                 if (r_shadow_shadowmapvsdct)
7690                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
7691
7692                 if (r_shadow_shadowmapsampler)
7693                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
7694                 if (r_shadow_shadowmappcf > 1)
7695                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
7696                 else if (r_shadow_shadowmappcf)
7697                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
7698         }
7699         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
7700         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
7701         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
7702         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
7703         switch(vid.renderpath)
7704         {
7705         case RENDERPATH_D3D9:
7706 #ifdef SUPPORTD3D
7707                 R_SetupShader_SetPermutationHLSL(mode, permutation);
7708                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
7709                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
7710                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
7711                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
7712                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
7713                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
7714                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
7715                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
7716                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
7717                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
7718
7719                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
7720                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
7721                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
7722                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
7723                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
7724                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
7725 #endif
7726                 break;
7727         case RENDERPATH_D3D10:
7728                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7729                 break;
7730         case RENDERPATH_D3D11:
7731                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7732                 break;
7733         case RENDERPATH_GL20:
7734         case RENDERPATH_GLES2:
7735                 R_SetupShader_SetPermutationGLSL(mode, permutation);
7736                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
7737                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
7738                 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);
7739                 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);
7740                 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);
7741                 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]);
7742                 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]);
7743                 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));
7744                 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]);
7745                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
7746
7747                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
7748                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
7749                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
7750                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
7751                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
7752                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
7753                 break;
7754         case RENDERPATH_CGGL:
7755 #ifdef SUPPORTCG
7756                 R_SetupShader_SetPermutationCG(mode, permutation);
7757                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
7758                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
7759                 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
7760                 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
7761                 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
7762                 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
7763                 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
7764                 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
7765                 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
7766                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7767
7768                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
7769                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
7770                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
7771                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
7772                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
7773                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
7774 #endif
7775                 break;
7776         case RENDERPATH_GL13:
7777         case RENDERPATH_GL11:
7778                 break;
7779         case RENDERPATH_SOFT:
7780                 R_SetupShader_SetPermutationGLSL(mode, permutation);
7781                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
7782                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
7783                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
7784                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
7785                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
7786                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
7787                 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]);
7788                 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));
7789                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
7790                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7791
7792                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
7793                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
7794                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
7795                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
7796                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
7797                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
7798                 break;
7799         }
7800 }
7801
7802 #define SKINFRAME_HASH 1024
7803
7804 typedef struct
7805 {
7806         int loadsequence; // incremented each level change
7807         memexpandablearray_t array;
7808         skinframe_t *hash[SKINFRAME_HASH];
7809 }
7810 r_skinframe_t;
7811 r_skinframe_t r_skinframe;
7812
7813 void R_SkinFrame_PrepareForPurge(void)
7814 {
7815         r_skinframe.loadsequence++;
7816         // wrap it without hitting zero
7817         if (r_skinframe.loadsequence >= 200)
7818                 r_skinframe.loadsequence = 1;
7819 }
7820
7821 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
7822 {
7823         if (!skinframe)
7824                 return;
7825         // mark the skinframe as used for the purging code
7826         skinframe->loadsequence = r_skinframe.loadsequence;
7827 }
7828
7829 void R_SkinFrame_Purge(void)
7830 {
7831         int i;
7832         skinframe_t *s;
7833         for (i = 0;i < SKINFRAME_HASH;i++)
7834         {
7835                 for (s = r_skinframe.hash[i];s;s = s->next)
7836                 {
7837                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
7838                         {
7839                                 if (s->merged == s->base)
7840                                         s->merged = NULL;
7841                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
7842                                 R_PurgeTexture(s->stain );s->stain  = NULL;
7843                                 R_PurgeTexture(s->merged);s->merged = NULL;
7844                                 R_PurgeTexture(s->base  );s->base   = NULL;
7845                                 R_PurgeTexture(s->pants );s->pants  = NULL;
7846                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
7847                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
7848                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
7849                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
7850                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
7851                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
7852                                 s->loadsequence = 0;
7853                         }
7854                 }
7855         }
7856 }
7857
7858 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
7859         skinframe_t *item;
7860         char basename[MAX_QPATH];
7861
7862         Image_StripImageExtension(name, basename, sizeof(basename));
7863
7864         if( last == NULL ) {
7865                 int hashindex;
7866                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
7867                 item = r_skinframe.hash[hashindex];
7868         } else {
7869                 item = last->next;
7870         }
7871
7872         // linearly search through the hash bucket
7873         for( ; item ; item = item->next ) {
7874                 if( !strcmp( item->basename, basename ) ) {
7875                         return item;
7876                 }
7877         }
7878         return NULL;
7879 }
7880
7881 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
7882 {
7883         skinframe_t *item;
7884         int hashindex;
7885         char basename[MAX_QPATH];
7886
7887         Image_StripImageExtension(name, basename, sizeof(basename));
7888
7889         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
7890         for (item = r_skinframe.hash[hashindex];item;item = item->next)
7891                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
7892                         break;
7893
7894         if (!item) {
7895                 rtexture_t *dyntexture;
7896                 // check whether its a dynamic texture
7897                 dyntexture = CL_GetDynTexture( basename );
7898                 if (!add && !dyntexture)
7899                         return NULL;
7900                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
7901                 memset(item, 0, sizeof(*item));
7902                 strlcpy(item->basename, basename, sizeof(item->basename));
7903                 item->base = dyntexture; // either NULL or dyntexture handle
7904                 item->textureflags = textureflags;
7905                 item->comparewidth = comparewidth;
7906                 item->compareheight = compareheight;
7907                 item->comparecrc = comparecrc;
7908                 item->next = r_skinframe.hash[hashindex];
7909                 r_skinframe.hash[hashindex] = item;
7910         }
7911         else if( item->base == NULL )
7912         {
7913                 rtexture_t *dyntexture;
7914                 // check whether its a dynamic texture
7915                 // 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]
7916                 dyntexture = CL_GetDynTexture( basename );
7917                 item->base = dyntexture; // either NULL or dyntexture handle
7918         }
7919
7920         R_SkinFrame_MarkUsed(item);
7921         return item;
7922 }
7923
7924 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
7925         { \
7926                 unsigned long long avgcolor[5], wsum; \
7927                 int pix, comp, w; \
7928                 avgcolor[0] = 0; \
7929                 avgcolor[1] = 0; \
7930                 avgcolor[2] = 0; \
7931                 avgcolor[3] = 0; \
7932                 avgcolor[4] = 0; \
7933                 wsum = 0; \
7934                 for(pix = 0; pix < cnt; ++pix) \
7935                 { \
7936                         w = 0; \
7937                         for(comp = 0; comp < 3; ++comp) \
7938                                 w += getpixel; \
7939                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
7940                         { \
7941                                 ++wsum; \
7942                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
7943                                 w = getpixel; \
7944                                 for(comp = 0; comp < 3; ++comp) \
7945                                         avgcolor[comp] += getpixel * w; \
7946                                 avgcolor[3] += w; \
7947                         } \
7948                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
7949                         avgcolor[4] += getpixel; \
7950                 } \
7951                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
7952                         avgcolor[3] = 1; \
7953                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
7954                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
7955                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
7956                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
7957         }
7958
7959 extern cvar_t gl_picmip;
7960 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
7961 {
7962         int j;
7963         unsigned char *pixels;
7964         unsigned char *bumppixels;
7965         unsigned char *basepixels = NULL;
7966         int basepixels_width = 0;
7967         int basepixels_height = 0;
7968         skinframe_t *skinframe;
7969         rtexture_t *ddsbase = NULL;
7970         qboolean ddshasalpha = false;
7971         float ddsavgcolor[4];
7972         char basename[MAX_QPATH];
7973         int miplevel = R_PicmipForFlags(textureflags);
7974         int savemiplevel = miplevel;
7975         int mymiplevel;
7976
7977         if (cls.state == ca_dedicated)
7978                 return NULL;
7979
7980         // return an existing skinframe if already loaded
7981         // if loading of the first image fails, don't make a new skinframe as it
7982         // would cause all future lookups of this to be missing
7983         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7984         if (skinframe && skinframe->base)
7985                 return skinframe;
7986
7987         Image_StripImageExtension(name, basename, sizeof(basename));
7988
7989         // check for DDS texture file first
7990         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
7991         {
7992                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
7993                 if (basepixels == NULL)
7994                         return NULL;
7995         }
7996
7997         // FIXME handle miplevel
7998
7999         if (developer_loading.integer)
8000                 Con_Printf("loading skin \"%s\"\n", name);
8001
8002         // we've got some pixels to store, so really allocate this new texture now
8003         if (!skinframe)
8004                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
8005         skinframe->stain = NULL;
8006         skinframe->merged = NULL;
8007         skinframe->base = NULL;
8008         skinframe->pants = NULL;
8009         skinframe->shirt = NULL;
8010         skinframe->nmap = NULL;
8011         skinframe->gloss = NULL;
8012         skinframe->glow = NULL;
8013         skinframe->fog = NULL;
8014         skinframe->reflect = NULL;
8015         skinframe->hasalpha = false;
8016
8017         if (ddsbase)
8018         {
8019                 skinframe->base = ddsbase;
8020                 skinframe->hasalpha = ddshasalpha;
8021                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
8022                 if (r_loadfog && skinframe->hasalpha)
8023                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
8024                 //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]);
8025         }
8026         else
8027         {
8028                 basepixels_width = image_width;
8029                 basepixels_height = image_height;
8030                 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);
8031                 if (textureflags & TEXF_ALPHA)
8032                 {
8033                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
8034                         {
8035                                 if (basepixels[j] < 255)
8036                                 {
8037                                         skinframe->hasalpha = true;
8038                                         break;
8039                                 }
8040                         }
8041                         if (r_loadfog && skinframe->hasalpha)
8042                         {
8043                                 // has transparent pixels
8044                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
8045                                 for (j = 0;j < image_width * image_height * 4;j += 4)
8046                                 {
8047                                         pixels[j+0] = 255;
8048                                         pixels[j+1] = 255;
8049                                         pixels[j+2] = 255;
8050                                         pixels[j+3] = basepixels[j+3];
8051                                 }
8052                                 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);
8053                                 Mem_Free(pixels);
8054                         }
8055                 }
8056                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
8057                 //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]);
8058                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
8059                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
8060                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
8061                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
8062         }
8063
8064         if (r_loaddds)
8065         {
8066                 mymiplevel = savemiplevel;
8067                 if (r_loadnormalmap)
8068                         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);
8069                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
8070                 if (r_loadgloss)
8071                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
8072                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
8073                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
8074                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
8075         }
8076
8077         // _norm is the name used by tenebrae and has been adopted as standard
8078         if (r_loadnormalmap && skinframe->nmap == NULL)
8079         {
8080                 mymiplevel = savemiplevel;
8081                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
8082                 {
8083                         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);
8084                         Mem_Free(pixels);
8085                         pixels = NULL;
8086                 }
8087                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
8088                 {
8089                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
8090                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
8091                         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);
8092                         Mem_Free(pixels);
8093                         Mem_Free(bumppixels);
8094                 }
8095                 else if (r_shadow_bumpscale_basetexture.value > 0)
8096                 {
8097                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
8098                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
8099                         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);
8100                         Mem_Free(pixels);
8101                 }
8102                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
8103                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
8104         }
8105
8106         // _luma is supported only for tenebrae compatibility
8107         // _glow is the preferred name
8108         mymiplevel = savemiplevel;
8109         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))))
8110         {
8111                 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);
8112                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
8113                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
8114                 Mem_Free(pixels);pixels = NULL;
8115         }
8116
8117         mymiplevel = savemiplevel;
8118         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
8119         {
8120                 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);
8121                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
8122                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
8123                 Mem_Free(pixels);
8124                 pixels = NULL;
8125         }
8126
8127         mymiplevel = savemiplevel;
8128         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
8129         {
8130                 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);
8131                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
8132                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
8133                 Mem_Free(pixels);
8134                 pixels = NULL;
8135         }
8136
8137         mymiplevel = savemiplevel;
8138         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
8139         {
8140                 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);
8141                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
8142                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
8143                 Mem_Free(pixels);
8144                 pixels = NULL;
8145         }
8146
8147         mymiplevel = savemiplevel;
8148         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
8149         {
8150                 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);
8151                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
8152                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
8153                 Mem_Free(pixels);
8154                 pixels = NULL;
8155         }
8156
8157         if (basepixels)
8158                 Mem_Free(basepixels);
8159
8160         return skinframe;
8161 }
8162
8163 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
8164 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
8165 {
8166         int i;
8167         unsigned char *temp1, *temp2;
8168         skinframe_t *skinframe;
8169
8170         if (cls.state == ca_dedicated)
8171                 return NULL;
8172
8173         // if already loaded just return it, otherwise make a new skinframe
8174         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
8175         if (skinframe && skinframe->base)
8176                 return skinframe;
8177
8178         skinframe->stain = NULL;
8179         skinframe->merged = NULL;
8180         skinframe->base = NULL;
8181         skinframe->pants = NULL;
8182         skinframe->shirt = NULL;
8183         skinframe->nmap = NULL;
8184         skinframe->gloss = NULL;
8185         skinframe->glow = NULL;
8186         skinframe->fog = NULL;
8187         skinframe->reflect = NULL;
8188         skinframe->hasalpha = false;
8189
8190         // if no data was provided, then clearly the caller wanted to get a blank skinframe
8191         if (!skindata)
8192                 return NULL;
8193
8194         if (developer_loading.integer)
8195                 Con_Printf("loading 32bit skin \"%s\"\n", name);
8196
8197         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
8198         {
8199                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
8200                 temp2 = temp1 + width * height * 4;
8201                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
8202                 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);
8203                 Mem_Free(temp1);
8204         }
8205         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
8206         if (textureflags & TEXF_ALPHA)
8207         {
8208                 for (i = 3;i < width * height * 4;i += 4)
8209                 {
8210                         if (skindata[i] < 255)
8211                         {
8212                                 skinframe->hasalpha = true;
8213                                 break;
8214                         }
8215                 }
8216                 if (r_loadfog && skinframe->hasalpha)
8217                 {
8218                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
8219                         memcpy(fogpixels, skindata, width * height * 4);
8220                         for (i = 0;i < width * height * 4;i += 4)
8221                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
8222                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
8223                         Mem_Free(fogpixels);
8224                 }
8225         }
8226
8227         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
8228         //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]);
8229
8230         return skinframe;
8231 }
8232
8233 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
8234 {
8235         int i;
8236         int featuresmask;
8237         skinframe_t *skinframe;
8238
8239         if (cls.state == ca_dedicated)
8240                 return NULL;
8241
8242         // if already loaded just return it, otherwise make a new skinframe
8243         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
8244         if (skinframe && skinframe->base)
8245                 return skinframe;
8246
8247         skinframe->stain = NULL;
8248         skinframe->merged = NULL;
8249         skinframe->base = NULL;
8250         skinframe->pants = NULL;
8251         skinframe->shirt = NULL;
8252         skinframe->nmap = NULL;
8253         skinframe->gloss = NULL;
8254         skinframe->glow = NULL;
8255         skinframe->fog = NULL;
8256         skinframe->reflect = NULL;
8257         skinframe->hasalpha = false;
8258
8259         // if no data was provided, then clearly the caller wanted to get a blank skinframe
8260         if (!skindata)
8261                 return NULL;
8262
8263         if (developer_loading.integer)
8264                 Con_Printf("loading quake skin \"%s\"\n", name);
8265
8266         // 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)
8267         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
8268         memcpy(skinframe->qpixels, skindata, width*height);
8269         skinframe->qwidth = width;
8270         skinframe->qheight = height;
8271
8272         featuresmask = 0;
8273         for (i = 0;i < width * height;i++)
8274                 featuresmask |= palette_featureflags[skindata[i]];
8275
8276         skinframe->hasalpha = false;
8277         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
8278         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
8279         skinframe->qgeneratemerged = true;
8280         skinframe->qgeneratebase = skinframe->qhascolormapping;
8281         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
8282
8283         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
8284         //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]);
8285
8286         return skinframe;
8287 }
8288
8289 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
8290 {
8291         int width;
8292         int height;
8293         unsigned char *skindata;
8294
8295         if (!skinframe->qpixels)
8296                 return;
8297
8298         if (!skinframe->qhascolormapping)
8299                 colormapped = false;
8300
8301         if (colormapped)
8302         {
8303                 if (!skinframe->qgeneratebase)
8304                         return;
8305         }
8306         else
8307         {
8308                 if (!skinframe->qgeneratemerged)
8309                         return;
8310         }
8311
8312         width = skinframe->qwidth;
8313         height = skinframe->qheight;
8314         skindata = skinframe->qpixels;
8315
8316         if (skinframe->qgeneratenmap)
8317         {
8318                 unsigned char *temp1, *temp2;
8319                 skinframe->qgeneratenmap = false;
8320                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
8321                 temp2 = temp1 + width * height * 4;
8322                 // use either a custom palette or the quake palette
8323                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
8324                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
8325                 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);
8326                 Mem_Free(temp1);
8327         }
8328
8329         if (skinframe->qgenerateglow)
8330         {
8331                 skinframe->qgenerateglow = false;
8332                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
8333         }
8334
8335         if (colormapped)
8336         {
8337                 skinframe->qgeneratebase = false;
8338                 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);
8339                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
8340                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
8341         }
8342         else
8343         {
8344                 skinframe->qgeneratemerged = false;
8345                 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);
8346         }
8347
8348         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
8349         {
8350                 Mem_Free(skinframe->qpixels);
8351                 skinframe->qpixels = NULL;
8352         }
8353 }
8354
8355 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)
8356 {
8357         int i;
8358         skinframe_t *skinframe;
8359
8360         if (cls.state == ca_dedicated)
8361                 return NULL;
8362
8363         // if already loaded just return it, otherwise make a new skinframe
8364         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
8365         if (skinframe && skinframe->base)
8366                 return skinframe;
8367
8368         skinframe->stain = NULL;
8369         skinframe->merged = NULL;
8370         skinframe->base = NULL;
8371         skinframe->pants = NULL;
8372         skinframe->shirt = NULL;
8373         skinframe->nmap = NULL;
8374         skinframe->gloss = NULL;
8375         skinframe->glow = NULL;
8376         skinframe->fog = NULL;
8377         skinframe->reflect = NULL;
8378         skinframe->hasalpha = false;
8379
8380         // if no data was provided, then clearly the caller wanted to get a blank skinframe
8381         if (!skindata)
8382                 return NULL;
8383
8384         if (developer_loading.integer)
8385                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
8386
8387         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
8388         if (textureflags & TEXF_ALPHA)
8389         {
8390                 for (i = 0;i < width * height;i++)
8391                 {
8392                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
8393                         {
8394                                 skinframe->hasalpha = true;
8395                                 break;
8396                         }
8397                 }
8398                 if (r_loadfog && skinframe->hasalpha)
8399                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
8400         }
8401
8402         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
8403         //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]);
8404
8405         return skinframe;
8406 }
8407
8408 skinframe_t *R_SkinFrame_LoadMissing(void)
8409 {
8410         skinframe_t *skinframe;
8411
8412         if (cls.state == ca_dedicated)
8413                 return NULL;
8414
8415         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
8416         skinframe->stain = NULL;
8417         skinframe->merged = NULL;
8418         skinframe->base = NULL;
8419         skinframe->pants = NULL;
8420         skinframe->shirt = NULL;
8421         skinframe->nmap = NULL;
8422         skinframe->gloss = NULL;
8423         skinframe->glow = NULL;
8424         skinframe->fog = NULL;
8425         skinframe->reflect = NULL;
8426         skinframe->hasalpha = false;
8427
8428         skinframe->avgcolor[0] = rand() / RAND_MAX;
8429         skinframe->avgcolor[1] = rand() / RAND_MAX;
8430         skinframe->avgcolor[2] = rand() / RAND_MAX;
8431         skinframe->avgcolor[3] = 1;
8432
8433         return skinframe;
8434 }
8435
8436 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
8437 typedef struct suffixinfo_s
8438 {
8439         const char *suffix;
8440         qboolean flipx, flipy, flipdiagonal;
8441 }
8442 suffixinfo_t;
8443 static suffixinfo_t suffix[3][6] =
8444 {
8445         {
8446                 {"px",   false, false, false},
8447                 {"nx",   false, false, false},
8448                 {"py",   false, false, false},
8449                 {"ny",   false, false, false},
8450                 {"pz",   false, false, false},
8451                 {"nz",   false, false, false}
8452         },
8453         {
8454                 {"posx", false, false, false},
8455                 {"negx", false, false, false},
8456                 {"posy", false, false, false},
8457                 {"negy", false, false, false},
8458                 {"posz", false, false, false},
8459                 {"negz", false, false, false}
8460         },
8461         {
8462                 {"rt",    true, false,  true},
8463                 {"lf",   false,  true,  true},
8464                 {"ft",    true,  true, false},
8465                 {"bk",   false, false, false},
8466                 {"up",    true, false,  true},
8467                 {"dn",    true, false,  true}
8468         }
8469 };
8470
8471 static int componentorder[4] = {0, 1, 2, 3};
8472
8473 rtexture_t *R_LoadCubemap(const char *basename)
8474 {
8475         int i, j, cubemapsize;
8476         unsigned char *cubemappixels, *image_buffer;
8477         rtexture_t *cubemaptexture;
8478         char name[256];
8479         // must start 0 so the first loadimagepixels has no requested width/height
8480         cubemapsize = 0;
8481         cubemappixels = NULL;
8482         cubemaptexture = NULL;
8483         // keep trying different suffix groups (posx, px, rt) until one loads
8484         for (j = 0;j < 3 && !cubemappixels;j++)
8485         {
8486                 // load the 6 images in the suffix group
8487                 for (i = 0;i < 6;i++)
8488                 {
8489                         // generate an image name based on the base and and suffix
8490                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
8491                         // load it
8492                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
8493                         {
8494                                 // an image loaded, make sure width and height are equal
8495                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
8496                                 {
8497                                         // if this is the first image to load successfully, allocate the cubemap memory
8498                                         if (!cubemappixels && image_width >= 1)
8499                                         {
8500                                                 cubemapsize = image_width;
8501                                                 // note this clears to black, so unavailable sides are black
8502                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
8503                                         }
8504                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
8505                                         if (cubemappixels)
8506                                                 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);
8507                                 }
8508                                 else
8509                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
8510                                 // free the image
8511                                 Mem_Free(image_buffer);
8512                         }
8513                 }
8514         }
8515         // if a cubemap loaded, upload it
8516         if (cubemappixels)
8517         {
8518                 if (developer_loading.integer)
8519                         Con_Printf("loading cubemap \"%s\"\n", basename);
8520
8521                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8522                 Mem_Free(cubemappixels);
8523         }
8524         else
8525         {
8526                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
8527                 if (developer_loading.integer)
8528                 {
8529                         Con_Printf("(tried tried images ");
8530                         for (j = 0;j < 3;j++)
8531                                 for (i = 0;i < 6;i++)
8532                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
8533                         Con_Print(" and was unable to find any of them).\n");
8534                 }
8535         }
8536         return cubemaptexture;
8537 }
8538
8539 rtexture_t *R_GetCubemap(const char *basename)
8540 {
8541         int i;
8542         for (i = 0;i < r_texture_numcubemaps;i++)
8543                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
8544                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
8545         if (i >= MAX_CUBEMAPS)
8546                 return r_texture_whitecube;
8547         r_texture_numcubemaps++;
8548         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
8549         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
8550         return r_texture_cubemaps[i].texture;
8551 }
8552
8553 void R_FreeCubemaps(void)
8554 {
8555         int i;
8556         for (i = 0;i < r_texture_numcubemaps;i++)
8557         {
8558                 if (developer_loading.integer)
8559                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
8560                 if (r_texture_cubemaps[i].texture)
8561                         R_FreeTexture(r_texture_cubemaps[i].texture);
8562         }
8563         r_texture_numcubemaps = 0;
8564 }
8565
8566 void R_Main_FreeViewCache(void)
8567 {
8568         if (r_refdef.viewcache.entityvisible)
8569                 Mem_Free(r_refdef.viewcache.entityvisible);
8570         if (r_refdef.viewcache.world_pvsbits)
8571                 Mem_Free(r_refdef.viewcache.world_pvsbits);
8572         if (r_refdef.viewcache.world_leafvisible)
8573                 Mem_Free(r_refdef.viewcache.world_leafvisible);
8574         if (r_refdef.viewcache.world_surfacevisible)
8575                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
8576         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
8577 }
8578
8579 void R_Main_ResizeViewCache(void)
8580 {
8581         int numentities = r_refdef.scene.numentities;
8582         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
8583         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
8584         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
8585         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
8586         if (r_refdef.viewcache.maxentities < numentities)
8587         {
8588                 r_refdef.viewcache.maxentities = numentities;
8589                 if (r_refdef.viewcache.entityvisible)
8590                         Mem_Free(r_refdef.viewcache.entityvisible);
8591                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
8592         }
8593         if (r_refdef.viewcache.world_numclusters != numclusters)
8594         {
8595                 r_refdef.viewcache.world_numclusters = numclusters;
8596                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
8597                 if (r_refdef.viewcache.world_pvsbits)
8598                         Mem_Free(r_refdef.viewcache.world_pvsbits);
8599                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
8600         }
8601         if (r_refdef.viewcache.world_numleafs != numleafs)
8602         {
8603                 r_refdef.viewcache.world_numleafs = numleafs;
8604                 if (r_refdef.viewcache.world_leafvisible)
8605                         Mem_Free(r_refdef.viewcache.world_leafvisible);
8606                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
8607         }
8608         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
8609         {
8610                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
8611                 if (r_refdef.viewcache.world_surfacevisible)
8612                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
8613                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
8614         }
8615 }
8616
8617 extern rtexture_t *loadingscreentexture;
8618 void gl_main_start(void)
8619 {
8620         loadingscreentexture = NULL;
8621         r_texture_blanknormalmap = NULL;
8622         r_texture_white = NULL;
8623         r_texture_grey128 = NULL;
8624         r_texture_black = NULL;
8625         r_texture_whitecube = NULL;
8626         r_texture_normalizationcube = NULL;
8627         r_texture_fogattenuation = NULL;
8628         r_texture_fogheighttexture = NULL;
8629         r_texture_gammaramps = NULL;
8630         r_texture_numcubemaps = 0;
8631
8632         r_loaddds = r_texture_dds_load.integer != 0;
8633         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
8634
8635         switch(vid.renderpath)
8636         {
8637         case RENDERPATH_GL20:
8638         case RENDERPATH_CGGL:
8639         case RENDERPATH_D3D9:
8640         case RENDERPATH_D3D10:
8641         case RENDERPATH_D3D11:
8642         case RENDERPATH_SOFT:
8643                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
8644                 Cvar_SetValueQuick(&gl_combine, 1);
8645                 Cvar_SetValueQuick(&r_glsl, 1);
8646                 r_loadnormalmap = true;
8647                 r_loadgloss = true;
8648                 r_loadfog = false;
8649                 break;
8650         case RENDERPATH_GL13:
8651                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
8652                 Cvar_SetValueQuick(&gl_combine, 1);
8653                 Cvar_SetValueQuick(&r_glsl, 0);
8654                 r_loadnormalmap = false;
8655                 r_loadgloss = false;
8656                 r_loadfog = true;
8657                 break;
8658         case RENDERPATH_GL11:
8659                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
8660                 Cvar_SetValueQuick(&gl_combine, 0);
8661                 Cvar_SetValueQuick(&r_glsl, 0);
8662                 r_loadnormalmap = false;
8663                 r_loadgloss = false;
8664                 r_loadfog = true;
8665                 break;
8666         case RENDERPATH_GLES2:
8667                 Cvar_SetValueQuick(&r_textureunits, 1);
8668                 Cvar_SetValueQuick(&gl_combine, 1);
8669                 Cvar_SetValueQuick(&r_glsl, 1);
8670                 r_loadnormalmap = true;
8671                 r_loadgloss = false;
8672                 r_loadfog = false;
8673                 break;
8674         }
8675
8676         R_AnimCache_Free();
8677         R_FrameData_Reset();
8678
8679         r_numqueries = 0;
8680         r_maxqueries = 0;
8681         memset(r_queries, 0, sizeof(r_queries));
8682
8683         r_qwskincache = NULL;
8684         r_qwskincache_size = 0;
8685
8686         // set up r_skinframe loading system for textures
8687         memset(&r_skinframe, 0, sizeof(r_skinframe));
8688         r_skinframe.loadsequence = 1;
8689         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
8690
8691         r_main_texturepool = R_AllocTexturePool();
8692         R_BuildBlankTextures();
8693         R_BuildNoTexture();
8694         if (vid.support.arb_texture_cube_map)
8695         {
8696                 R_BuildWhiteCube();
8697                 R_BuildNormalizationCube();
8698         }
8699         r_texture_fogattenuation = NULL;
8700         r_texture_fogheighttexture = NULL;
8701         r_texture_gammaramps = NULL;
8702         //r_texture_fogintensity = NULL;
8703         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
8704         memset(&r_waterstate, 0, sizeof(r_waterstate));
8705         r_glsl_permutation = NULL;
8706         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
8707         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
8708         glslshaderstring = NULL;
8709 #ifdef SUPPORTCG
8710         r_cg_permutation = NULL;
8711         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
8712         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
8713         cgshaderstring = NULL;
8714 #endif
8715 #ifdef SUPPORTD3D
8716         r_hlsl_permutation = NULL;
8717         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
8718         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
8719         hlslshaderstring = NULL;
8720 #endif
8721         memset(&r_svbsp, 0, sizeof (r_svbsp));
8722
8723         r_refdef.fogmasktable_density = 0;
8724 }
8725
8726 void gl_main_shutdown(void)
8727 {
8728         R_AnimCache_Free();
8729         R_FrameData_Reset();
8730
8731         R_Main_FreeViewCache();
8732
8733         switch(vid.renderpath)
8734         {
8735         case RENDERPATH_GL11:
8736         case RENDERPATH_GL13:
8737         case RENDERPATH_GL20:
8738         case RENDERPATH_CGGL:
8739                 if (r_maxqueries)
8740                         qglDeleteQueriesARB(r_maxqueries, r_queries);
8741                 break;
8742         case RENDERPATH_D3D9:
8743                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8744                 break;
8745         case RENDERPATH_D3D10:
8746                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8747                 break;
8748         case RENDERPATH_D3D11:
8749                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8750                 break;
8751         case RENDERPATH_SOFT:
8752                 break;
8753         case RENDERPATH_GLES2:
8754                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8755                 break;
8756         }
8757
8758         r_numqueries = 0;
8759         r_maxqueries = 0;
8760         memset(r_queries, 0, sizeof(r_queries));
8761
8762         r_qwskincache = NULL;
8763         r_qwskincache_size = 0;
8764
8765         // clear out the r_skinframe state
8766         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
8767         memset(&r_skinframe, 0, sizeof(r_skinframe));
8768
8769         if (r_svbsp.nodes)
8770                 Mem_Free(r_svbsp.nodes);
8771         memset(&r_svbsp, 0, sizeof (r_svbsp));
8772         R_FreeTexturePool(&r_main_texturepool);
8773         loadingscreentexture = NULL;
8774         r_texture_blanknormalmap = NULL;
8775         r_texture_white = NULL;
8776         r_texture_grey128 = NULL;
8777         r_texture_black = NULL;
8778         r_texture_whitecube = NULL;
8779         r_texture_normalizationcube = NULL;
8780         r_texture_fogattenuation = NULL;
8781         r_texture_fogheighttexture = NULL;
8782         r_texture_gammaramps = NULL;
8783         r_texture_numcubemaps = 0;
8784         //r_texture_fogintensity = NULL;
8785         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
8786         memset(&r_waterstate, 0, sizeof(r_waterstate));
8787         R_GLSL_Restart_f();
8788
8789         r_glsl_permutation = NULL;
8790         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
8791         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
8792         glslshaderstring = NULL;
8793 #ifdef SUPPORTCG
8794         r_cg_permutation = NULL;
8795         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
8796         Mem_ExpandableArray_FreeArray(&r_cg_permutationarray);
8797         cgshaderstring = NULL;
8798 #endif
8799 #ifdef SUPPORTD3D
8800         r_hlsl_permutation = NULL;
8801         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
8802         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
8803         hlslshaderstring = NULL;
8804 #endif
8805 }
8806
8807 extern void CL_ParseEntityLump(char *entitystring);
8808 void gl_main_newmap(void)
8809 {
8810         // FIXME: move this code to client
8811         char *entities, entname[MAX_QPATH];
8812         if (r_qwskincache)
8813                 Mem_Free(r_qwskincache);
8814         r_qwskincache = NULL;
8815         r_qwskincache_size = 0;
8816         if (cl.worldmodel)
8817         {
8818                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
8819                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
8820                 {
8821                         CL_ParseEntityLump(entities);
8822                         Mem_Free(entities);
8823                         return;
8824                 }
8825                 if (cl.worldmodel->brush.entities)
8826                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
8827         }
8828         R_Main_FreeViewCache();
8829
8830         R_FrameData_Reset();
8831 }
8832
8833 void GL_Main_Init(void)
8834 {
8835         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
8836
8837         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
8838         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
8839         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
8840         if (gamemode == GAME_NEHAHRA)
8841         {
8842                 Cvar_RegisterVariable (&gl_fogenable);
8843                 Cvar_RegisterVariable (&gl_fogdensity);
8844                 Cvar_RegisterVariable (&gl_fogred);
8845                 Cvar_RegisterVariable (&gl_foggreen);
8846                 Cvar_RegisterVariable (&gl_fogblue);
8847                 Cvar_RegisterVariable (&gl_fogstart);
8848                 Cvar_RegisterVariable (&gl_fogend);
8849                 Cvar_RegisterVariable (&gl_skyclip);
8850         }
8851         Cvar_RegisterVariable(&r_motionblur);
8852         Cvar_RegisterVariable(&r_motionblur_maxblur);
8853         Cvar_RegisterVariable(&r_motionblur_bmin);
8854         Cvar_RegisterVariable(&r_motionblur_vmin);
8855         Cvar_RegisterVariable(&r_motionblur_vmax);
8856         Cvar_RegisterVariable(&r_motionblur_vcoeff);
8857         Cvar_RegisterVariable(&r_motionblur_randomize);
8858         Cvar_RegisterVariable(&r_damageblur);
8859         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
8860         Cvar_RegisterVariable(&r_equalize_entities_minambient);
8861         Cvar_RegisterVariable(&r_equalize_entities_by);
8862         Cvar_RegisterVariable(&r_equalize_entities_to);
8863         Cvar_RegisterVariable(&r_depthfirst);
8864         Cvar_RegisterVariable(&r_useinfinitefarclip);
8865         Cvar_RegisterVariable(&r_farclip_base);
8866         Cvar_RegisterVariable(&r_farclip_world);
8867         Cvar_RegisterVariable(&r_nearclip);
8868         Cvar_RegisterVariable(&r_showbboxes);
8869         Cvar_RegisterVariable(&r_showsurfaces);
8870         Cvar_RegisterVariable(&r_showtris);
8871         Cvar_RegisterVariable(&r_shownormals);
8872         Cvar_RegisterVariable(&r_showlighting);
8873         Cvar_RegisterVariable(&r_showshadowvolumes);
8874         Cvar_RegisterVariable(&r_showcollisionbrushes);
8875         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
8876         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
8877         Cvar_RegisterVariable(&r_showdisabledepthtest);
8878         Cvar_RegisterVariable(&r_drawportals);
8879         Cvar_RegisterVariable(&r_drawentities);
8880         Cvar_RegisterVariable(&r_draw2d);
8881         Cvar_RegisterVariable(&r_drawworld);
8882         Cvar_RegisterVariable(&r_cullentities_trace);
8883         Cvar_RegisterVariable(&r_cullentities_trace_samples);
8884         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
8885         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
8886         Cvar_RegisterVariable(&r_cullentities_trace_delay);
8887         Cvar_RegisterVariable(&r_drawviewmodel);
8888         Cvar_RegisterVariable(&r_drawexteriormodel);
8889         Cvar_RegisterVariable(&r_speeds);
8890         Cvar_RegisterVariable(&r_fullbrights);
8891         Cvar_RegisterVariable(&r_wateralpha);
8892         Cvar_RegisterVariable(&r_dynamic);
8893         Cvar_RegisterVariable(&r_fakelight);
8894         Cvar_RegisterVariable(&r_fakelight_intensity);
8895         Cvar_RegisterVariable(&r_fullbright);
8896         Cvar_RegisterVariable(&r_shadows);
8897         Cvar_RegisterVariable(&r_shadows_darken);
8898         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
8899         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
8900         Cvar_RegisterVariable(&r_shadows_throwdistance);
8901         Cvar_RegisterVariable(&r_shadows_throwdirection);
8902         Cvar_RegisterVariable(&r_shadows_focus);
8903         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
8904         Cvar_RegisterVariable(&r_q1bsp_skymasking);
8905         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
8906         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
8907         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
8908         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
8909         Cvar_RegisterVariable(&r_fog_exp2);
8910         Cvar_RegisterVariable(&r_drawfog);
8911         Cvar_RegisterVariable(&r_transparentdepthmasking);
8912         Cvar_RegisterVariable(&r_texture_dds_load);
8913         Cvar_RegisterVariable(&r_texture_dds_save);
8914         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
8915         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
8916         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
8917         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
8918         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
8919         Cvar_RegisterVariable(&r_textureunits);
8920         Cvar_RegisterVariable(&gl_combine);
8921         Cvar_RegisterVariable(&r_glsl);
8922         Cvar_RegisterVariable(&r_glsl_deluxemapping);
8923         Cvar_RegisterVariable(&r_glsl_offsetmapping);
8924         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
8925         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
8926         Cvar_RegisterVariable(&r_glsl_postprocess);
8927         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
8928         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
8929         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
8930         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
8931         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
8932         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
8933         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
8934         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
8935
8936         Cvar_RegisterVariable(&r_water);
8937         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
8938         Cvar_RegisterVariable(&r_water_clippingplanebias);
8939         Cvar_RegisterVariable(&r_water_refractdistort);
8940         Cvar_RegisterVariable(&r_water_reflectdistort);
8941         Cvar_RegisterVariable(&r_water_scissormode);
8942         Cvar_RegisterVariable(&r_lerpsprites);
8943         Cvar_RegisterVariable(&r_lerpmodels);
8944         Cvar_RegisterVariable(&r_lerplightstyles);
8945         Cvar_RegisterVariable(&r_waterscroll);
8946         Cvar_RegisterVariable(&r_bloom);
8947         Cvar_RegisterVariable(&r_bloom_colorscale);
8948         Cvar_RegisterVariable(&r_bloom_brighten);
8949         Cvar_RegisterVariable(&r_bloom_blur);
8950         Cvar_RegisterVariable(&r_bloom_resolution);
8951         Cvar_RegisterVariable(&r_bloom_colorexponent);
8952         Cvar_RegisterVariable(&r_bloom_colorsubtract);
8953         Cvar_RegisterVariable(&r_hdr);
8954         Cvar_RegisterVariable(&r_hdr_scenebrightness);
8955         Cvar_RegisterVariable(&r_hdr_glowintensity);
8956         Cvar_RegisterVariable(&r_hdr_range);
8957         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
8958         Cvar_RegisterVariable(&developer_texturelogging);
8959         Cvar_RegisterVariable(&gl_lightmaps);
8960         Cvar_RegisterVariable(&r_test);
8961         Cvar_RegisterVariable(&r_glsl_saturation);
8962         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
8963         Cvar_RegisterVariable(&r_framedatasize);
8964         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
8965                 Cvar_SetValue("r_fullbrights", 0);
8966         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
8967
8968         Cvar_RegisterVariable(&r_track_sprites);
8969         Cvar_RegisterVariable(&r_track_sprites_flags);
8970         Cvar_RegisterVariable(&r_track_sprites_scalew);
8971         Cvar_RegisterVariable(&r_track_sprites_scaleh);
8972         Cvar_RegisterVariable(&r_overheadsprites_perspective);
8973         Cvar_RegisterVariable(&r_overheadsprites_pushback);
8974         Cvar_RegisterVariable(&r_overheadsprites_scalex);
8975         Cvar_RegisterVariable(&r_overheadsprites_scaley);
8976 }
8977
8978 extern void R_Textures_Init(void);
8979 extern void GL_Draw_Init(void);
8980 extern void GL_Main_Init(void);
8981 extern void R_Shadow_Init(void);
8982 extern void R_Sky_Init(void);
8983 extern void GL_Surf_Init(void);
8984 extern void R_Particles_Init(void);
8985 extern void R_Explosion_Init(void);
8986 extern void gl_backend_init(void);
8987 extern void Sbar_Init(void);
8988 extern void R_LightningBeams_Init(void);
8989 extern void Mod_RenderInit(void);
8990 extern void Font_Init(void);
8991
8992 void Render_Init(void)
8993 {
8994         gl_backend_init();
8995         R_Textures_Init();
8996         GL_Main_Init();
8997         Font_Init();
8998         GL_Draw_Init();
8999         R_Shadow_Init();
9000         R_Sky_Init();
9001         GL_Surf_Init();
9002         Sbar_Init();
9003         R_Particles_Init();
9004         R_Explosion_Init();
9005         R_LightningBeams_Init();
9006         Mod_RenderInit();
9007 }
9008
9009 /*
9010 ===============
9011 GL_Init
9012 ===============
9013 */
9014 extern char *ENGINE_EXTENSIONS;
9015 void GL_Init (void)
9016 {
9017         gl_renderer = (const char *)qglGetString(GL_RENDERER);
9018         gl_vendor = (const char *)qglGetString(GL_VENDOR);
9019         gl_version = (const char *)qglGetString(GL_VERSION);
9020         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
9021
9022         if (!gl_extensions)
9023                 gl_extensions = "";
9024         if (!gl_platformextensions)
9025                 gl_platformextensions = "";
9026
9027         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
9028         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
9029         Con_Printf("GL_VERSION: %s\n", gl_version);
9030         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
9031         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
9032
9033         VID_CheckExtensions();
9034
9035         // LordHavoc: report supported extensions
9036         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
9037
9038         // clear to black (loading plaque will be seen over this)
9039         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
9040 }
9041
9042 int R_CullBox(const vec3_t mins, const vec3_t maxs)
9043 {
9044         int i;
9045         mplane_t *p;
9046         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
9047         {
9048                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
9049                 if (i == 4)
9050                         continue;
9051                 p = r_refdef.view.frustum + i;
9052                 switch(p->signbits)
9053                 {
9054                 default:
9055                 case 0:
9056                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
9057                                 return true;
9058                         break;
9059                 case 1:
9060                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
9061                                 return true;
9062                         break;
9063                 case 2:
9064                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
9065                                 return true;
9066                         break;
9067                 case 3:
9068                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
9069                                 return true;
9070                         break;
9071                 case 4:
9072                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
9073                                 return true;
9074                         break;
9075                 case 5:
9076                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
9077                                 return true;
9078                         break;
9079                 case 6:
9080                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
9081                                 return true;
9082                         break;
9083                 case 7:
9084                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
9085                                 return true;
9086                         break;
9087                 }
9088         }
9089         return false;
9090 }
9091
9092 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
9093 {
9094         int i;
9095         const mplane_t *p;
9096         for (i = 0;i < numplanes;i++)
9097         {
9098                 p = planes + i;
9099                 switch(p->signbits)
9100                 {
9101                 default:
9102                 case 0:
9103                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
9104                                 return true;
9105                         break;
9106                 case 1:
9107                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
9108                                 return true;
9109                         break;
9110                 case 2:
9111                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
9112                                 return true;
9113                         break;
9114                 case 3:
9115                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
9116                                 return true;
9117                         break;
9118                 case 4:
9119                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
9120                                 return true;
9121                         break;
9122                 case 5:
9123                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
9124                                 return true;
9125                         break;
9126                 case 6:
9127                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
9128                                 return true;
9129                         break;
9130                 case 7:
9131                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
9132                                 return true;
9133                         break;
9134                 }
9135         }
9136         return false;
9137 }
9138
9139 //==================================================================================
9140
9141 // LordHavoc: this stores temporary data used within the same frame
9142
9143 typedef struct r_framedata_mem_s
9144 {
9145         struct r_framedata_mem_s *purge; // older mem block to free on next frame
9146         size_t size; // how much usable space
9147         size_t current; // how much space in use
9148         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
9149         size_t wantedsize; // how much space was allocated
9150         unsigned char *data; // start of real data (16byte aligned)
9151 }
9152 r_framedata_mem_t;
9153
9154 static r_framedata_mem_t *r_framedata_mem;
9155
9156 void R_FrameData_Reset(void)
9157 {
9158         while (r_framedata_mem)
9159         {
9160                 r_framedata_mem_t *next = r_framedata_mem->purge;
9161                 Mem_Free(r_framedata_mem);
9162                 r_framedata_mem = next;
9163         }
9164 }
9165
9166 void R_FrameData_Resize(void)
9167 {
9168         size_t wantedsize;
9169         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
9170         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
9171         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
9172         {
9173                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
9174                 newmem->wantedsize = wantedsize;
9175                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
9176                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
9177                 newmem->current = 0;
9178                 newmem->mark = 0;
9179                 newmem->purge = r_framedata_mem;
9180                 r_framedata_mem = newmem;
9181         }
9182 }
9183
9184 void R_FrameData_NewFrame(void)
9185 {
9186         R_FrameData_Resize();
9187         if (!r_framedata_mem)
9188                 return;
9189         // if we ran out of space on the last frame, free the old memory now
9190         while (r_framedata_mem->purge)
9191         {
9192                 // repeatedly remove the second item in the list, leaving only head
9193                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
9194                 Mem_Free(r_framedata_mem->purge);
9195                 r_framedata_mem->purge = next;
9196         }
9197         // reset the current mem pointer
9198         r_framedata_mem->current = 0;
9199         r_framedata_mem->mark = 0;
9200 }
9201
9202 void *R_FrameData_Alloc(size_t size)
9203 {
9204         void *data;
9205
9206         // align to 16 byte boundary - the data pointer is already aligned, so we
9207         // only need to ensure the size of every allocation is also aligned
9208         size = (size + 15) & ~15;
9209
9210         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
9211         {
9212                 // emergency - we ran out of space, allocate more memory
9213                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
9214                 R_FrameData_Resize();
9215         }
9216
9217         data = r_framedata_mem->data + r_framedata_mem->current;
9218         r_framedata_mem->current += size;
9219
9220         // count the usage for stats
9221         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
9222         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
9223
9224         return (void *)data;
9225 }
9226
9227 void *R_FrameData_Store(size_t size, void *data)
9228 {
9229         void *d = R_FrameData_Alloc(size);
9230         if (d && data)
9231                 memcpy(d, data, size);
9232         return d;
9233 }
9234
9235 void R_FrameData_SetMark(void)
9236 {
9237         if (!r_framedata_mem)
9238                 return;
9239         r_framedata_mem->mark = r_framedata_mem->current;
9240 }
9241
9242 void R_FrameData_ReturnToMark(void)
9243 {
9244         if (!r_framedata_mem)
9245                 return;
9246         r_framedata_mem->current = r_framedata_mem->mark;
9247 }
9248
9249 //==================================================================================
9250
9251 // LordHavoc: animcache originally written by Echon, rewritten since then
9252
9253 /**
9254  * Animation cache prevents re-generating mesh data for an animated model
9255  * multiple times in one frame for lighting, shadowing, reflections, etc.
9256  */
9257
9258 void R_AnimCache_Free(void)
9259 {
9260 }
9261
9262 void R_AnimCache_ClearCache(void)
9263 {
9264         int i;
9265         entity_render_t *ent;
9266
9267         for (i = 0;i < r_refdef.scene.numentities;i++)
9268         {
9269                 ent = r_refdef.scene.entities[i];
9270                 ent->animcache_vertex3f = NULL;
9271                 ent->animcache_normal3f = NULL;
9272                 ent->animcache_svector3f = NULL;
9273                 ent->animcache_tvector3f = NULL;
9274                 ent->animcache_vertexmesh = NULL;
9275                 ent->animcache_vertex3fbuffer = NULL;
9276                 ent->animcache_vertexmeshbuffer = NULL;
9277         }
9278 }
9279
9280 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
9281 {
9282         int i;
9283
9284         // check if we need the meshbuffers
9285         if (!vid.useinterleavedarrays)
9286                 return;
9287
9288         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
9289                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
9290         // TODO: upload vertex3f buffer?
9291         if (ent->animcache_vertexmesh)
9292         {
9293                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
9294                 for (i = 0;i < numvertices;i++)
9295                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
9296                 if (ent->animcache_svector3f)
9297                         for (i = 0;i < numvertices;i++)
9298                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
9299                 if (ent->animcache_tvector3f)
9300                         for (i = 0;i < numvertices;i++)
9301                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
9302                 if (ent->animcache_normal3f)
9303                         for (i = 0;i < numvertices;i++)
9304                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
9305                 // TODO: upload vertexmeshbuffer?
9306         }
9307 }
9308
9309 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
9310 {
9311         dp_model_t *model = ent->model;
9312         int numvertices;
9313         // see if it's already cached this frame
9314         if (ent->animcache_vertex3f)
9315         {
9316                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
9317                 if (wantnormals || wanttangents)
9318                 {
9319                         if (ent->animcache_normal3f)
9320                                 wantnormals = false;
9321                         if (ent->animcache_svector3f)
9322                                 wanttangents = false;
9323                         if (wantnormals || wanttangents)
9324                         {
9325                                 numvertices = model->surfmesh.num_vertices;
9326                                 if (wantnormals)
9327                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
9328                                 if (wanttangents)
9329                                 {
9330                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
9331                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
9332                                 }
9333                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
9334                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
9335                         }
9336                 }
9337         }
9338         else
9339         {
9340                 // see if this ent is worth caching
9341                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
9342                         return false;
9343                 // get some memory for this entity and generate mesh data
9344                 numvertices = model->surfmesh.num_vertices;
9345                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
9346                 if (wantnormals)
9347                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
9348                 if (wanttangents)
9349                 {
9350                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
9351                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
9352                 }
9353                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
9354                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
9355         }
9356         return true;
9357 }
9358
9359 void R_AnimCache_CacheVisibleEntities(void)
9360 {
9361         int i;
9362         qboolean wantnormals = true;
9363         qboolean wanttangents = !r_showsurfaces.integer;
9364
9365         switch(vid.renderpath)
9366         {
9367         case RENDERPATH_GL20:
9368         case RENDERPATH_CGGL:
9369         case RENDERPATH_D3D9:
9370         case RENDERPATH_D3D10:
9371         case RENDERPATH_D3D11:
9372         case RENDERPATH_GLES2:
9373                 break;
9374         case RENDERPATH_GL13:
9375         case RENDERPATH_GL11:
9376                 wanttangents = false;
9377                 break;
9378         case RENDERPATH_SOFT:
9379                 break;
9380         }
9381
9382         if (r_shownormals.integer)
9383                 wanttangents = wantnormals = true;
9384
9385         // TODO: thread this
9386         // NOTE: R_PrepareRTLights() also caches entities
9387
9388         for (i = 0;i < r_refdef.scene.numentities;i++)
9389                 if (r_refdef.viewcache.entityvisible[i])
9390                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
9391 }
9392
9393 //==================================================================================
9394
9395 static void R_View_UpdateEntityLighting (void)
9396 {
9397         int i;
9398         entity_render_t *ent;
9399         vec3_t tempdiffusenormal, avg;
9400         vec_t f, fa, fd, fdd;
9401         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
9402
9403         for (i = 0;i < r_refdef.scene.numentities;i++)
9404         {
9405                 ent = r_refdef.scene.entities[i];
9406
9407                 // skip unseen models
9408                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
9409                         continue;
9410
9411                 // skip bsp models
9412                 if (ent->model && ent->model->brush.num_leafs)
9413                 {
9414                         // TODO: use modellight for r_ambient settings on world?
9415                         VectorSet(ent->modellight_ambient, 0, 0, 0);
9416                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
9417                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
9418                         continue;
9419                 }
9420
9421                 // fetch the lighting from the worldmodel data
9422                 VectorClear(ent->modellight_ambient);
9423                 VectorClear(ent->modellight_diffuse);
9424                 VectorClear(tempdiffusenormal);
9425                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
9426                 {
9427                         vec3_t org;
9428                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9429
9430                         // complete lightning for lit sprites
9431                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
9432                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
9433                         {
9434                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
9435                                         org[2] = org[2] + r_overheadsprites_pushback.value;
9436                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
9437                         }
9438                         else
9439                                 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
9440
9441                         if(ent->flags & RENDER_EQUALIZE)
9442                         {
9443                                 // first fix up ambient lighting...
9444                                 if(r_equalize_entities_minambient.value > 0)
9445                                 {
9446                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
9447                                         if(fd > 0)
9448                                         {
9449                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
9450                                                 if(fa < r_equalize_entities_minambient.value * fd)
9451                                                 {
9452                                                         // solve:
9453                                                         //   fa'/fd' = minambient
9454                                                         //   fa'+0.25*fd' = fa+0.25*fd
9455                                                         //   ...
9456                                                         //   fa' = fd' * minambient
9457                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
9458                                                         //   ...
9459                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
9460                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
9461                                                         //   ...
9462                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
9463                                                         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
9464                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
9465                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
9466                                                 }
9467                                         }
9468                                 }
9469
9470                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
9471                                 {
9472                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
9473                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
9474                                         f = fa + 0.25 * fd;
9475                                         if(f > 0)
9476                                         {
9477                                                 // adjust brightness and saturation to target
9478                                                 avg[0] = avg[1] = avg[2] = fa / f;
9479                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
9480                                                 avg[0] = avg[1] = avg[2] = fd / f;
9481                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
9482                                         }
9483                                 }
9484                         }
9485                 }
9486                 else // highly rare
9487                         VectorSet(ent->modellight_ambient, 1, 1, 1);
9488
9489                 // move the light direction into modelspace coordinates for lighting code
9490                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
9491                 if(VectorLength2(ent->modellight_lightdir) == 0)
9492                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
9493                 VectorNormalize(ent->modellight_lightdir);
9494         }
9495 }
9496
9497 #define MAX_LINEOFSIGHTTRACES 64
9498
9499 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
9500 {
9501         int i;
9502         vec3_t boxmins, boxmaxs;
9503         vec3_t start;
9504         vec3_t end;
9505         dp_model_t *model = r_refdef.scene.worldmodel;
9506
9507         if (!model || !model->brush.TraceLineOfSight)
9508                 return true;
9509
9510         // expand the box a little
9511         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
9512         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
9513         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
9514         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
9515         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
9516         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
9517
9518         // return true if eye is inside enlarged box
9519         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
9520                 return true;
9521
9522         // try center
9523         VectorCopy(eye, start);
9524         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
9525         if (model->brush.TraceLineOfSight(model, start, end))
9526                 return true;
9527
9528         // try various random positions
9529         for (i = 0;i < numsamples;i++)
9530         {
9531                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
9532                 if (model->brush.TraceLineOfSight(model, start, end))
9533                         return true;
9534         }
9535
9536         return false;
9537 }
9538
9539
9540 static void R_View_UpdateEntityVisible (void)
9541 {
9542         int i;
9543         int renderimask;
9544         int samples;
9545         entity_render_t *ent;
9546
9547         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
9548                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
9549                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
9550                 :                                                          RENDER_EXTERIORMODEL;
9551         if (!r_drawviewmodel.integer)
9552                 renderimask |= RENDER_VIEWMODEL;
9553         if (!r_drawexteriormodel.integer)
9554                 renderimask |= RENDER_EXTERIORMODEL;
9555         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
9556         {
9557                 // worldmodel can check visibility
9558                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
9559                 for (i = 0;i < r_refdef.scene.numentities;i++)
9560                 {
9561                         ent = r_refdef.scene.entities[i];
9562                         if (!(ent->flags & renderimask))
9563                         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)))
9564                         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))
9565                                 r_refdef.viewcache.entityvisible[i] = true;
9566                 }
9567                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
9568                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
9569                 {
9570                         for (i = 0;i < r_refdef.scene.numentities;i++)
9571                         {
9572                                 ent = r_refdef.scene.entities[i];
9573                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
9574                                 {
9575                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
9576                                         if (samples < 0)
9577                                                 continue; // temp entities do pvs only
9578                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
9579                                                 ent->last_trace_visibility = realtime;
9580                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
9581                                                 r_refdef.viewcache.entityvisible[i] = 0;
9582                                 }
9583                         }
9584                 }
9585         }
9586         else
9587         {
9588                 // no worldmodel or it can't check visibility
9589                 for (i = 0;i < r_refdef.scene.numentities;i++)
9590                 {
9591                         ent = r_refdef.scene.entities[i];
9592                         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));
9593                 }
9594         }
9595 }
9596
9597 /// only used if skyrendermasked, and normally returns false
9598 int R_DrawBrushModelsSky (void)
9599 {
9600         int i, sky;
9601         entity_render_t *ent;
9602
9603         sky = false;
9604         for (i = 0;i < r_refdef.scene.numentities;i++)
9605         {
9606                 if (!r_refdef.viewcache.entityvisible[i])
9607                         continue;
9608                 ent = r_refdef.scene.entities[i];
9609                 if (!ent->model || !ent->model->DrawSky)
9610                         continue;
9611                 ent->model->DrawSky(ent);
9612                 sky = true;
9613         }
9614         return sky;
9615 }
9616
9617 static void R_DrawNoModel(entity_render_t *ent);
9618 static void R_DrawModels(void)
9619 {
9620         int i;
9621         entity_render_t *ent;
9622
9623         for (i = 0;i < r_refdef.scene.numentities;i++)
9624         {
9625                 if (!r_refdef.viewcache.entityvisible[i])
9626                         continue;
9627                 ent = r_refdef.scene.entities[i];
9628                 r_refdef.stats.entities++;
9629                 if (ent->model && ent->model->Draw != NULL)
9630                         ent->model->Draw(ent);
9631                 else
9632                         R_DrawNoModel(ent);
9633         }
9634 }
9635
9636 static void R_DrawModelsDepth(void)
9637 {
9638         int i;
9639         entity_render_t *ent;
9640
9641         for (i = 0;i < r_refdef.scene.numentities;i++)
9642         {
9643                 if (!r_refdef.viewcache.entityvisible[i])
9644                         continue;
9645                 ent = r_refdef.scene.entities[i];
9646                 if (ent->model && ent->model->DrawDepth != NULL)
9647                         ent->model->DrawDepth(ent);
9648         }
9649 }
9650
9651 static void R_DrawModelsDebug(void)
9652 {
9653         int i;
9654         entity_render_t *ent;
9655
9656         for (i = 0;i < r_refdef.scene.numentities;i++)
9657         {
9658                 if (!r_refdef.viewcache.entityvisible[i])
9659                         continue;
9660                 ent = r_refdef.scene.entities[i];
9661                 if (ent->model && ent->model->DrawDebug != NULL)
9662                         ent->model->DrawDebug(ent);
9663         }
9664 }
9665
9666 static void R_DrawModelsAddWaterPlanes(void)
9667 {
9668         int i;
9669         entity_render_t *ent;
9670
9671         for (i = 0;i < r_refdef.scene.numentities;i++)
9672         {
9673                 if (!r_refdef.viewcache.entityvisible[i])
9674                         continue;
9675                 ent = r_refdef.scene.entities[i];
9676                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
9677                         ent->model->DrawAddWaterPlanes(ent);
9678         }
9679 }
9680
9681 static void R_View_SetFrustum(const int *scissor)
9682 {
9683         int i;
9684         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
9685         vec3_t forward, left, up, origin, v;
9686
9687         if(scissor)
9688         {
9689                 // flipped x coordinates (because x points left here)
9690                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
9691                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
9692
9693                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
9694                 switch(vid.renderpath)
9695                 {
9696                         case RENDERPATH_D3D9:
9697                         case RENDERPATH_D3D10:
9698                         case RENDERPATH_D3D11:
9699                         case RENDERPATH_SOFT:
9700                                 // non-flipped y coordinates
9701                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
9702                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
9703                                 break;
9704                         case RENDERPATH_GL11:
9705                         case RENDERPATH_GL13:
9706                         case RENDERPATH_GL20:
9707                         case RENDERPATH_CGGL:
9708                         case RENDERPATH_GLES2:
9709                                 // non-flipped y coordinates
9710                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
9711                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
9712                                 break;
9713                 }
9714         }
9715
9716         // we can't trust r_refdef.view.forward and friends in reflected scenes
9717         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
9718
9719 #if 0
9720         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
9721         r_refdef.view.frustum[0].normal[1] = 0 - 0;
9722         r_refdef.view.frustum[0].normal[2] = -1 - 0;
9723         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
9724         r_refdef.view.frustum[1].normal[1] = 0 + 0;
9725         r_refdef.view.frustum[1].normal[2] = -1 + 0;
9726         r_refdef.view.frustum[2].normal[0] = 0 - 0;
9727         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
9728         r_refdef.view.frustum[2].normal[2] = -1 - 0;
9729         r_refdef.view.frustum[3].normal[0] = 0 + 0;
9730         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
9731         r_refdef.view.frustum[3].normal[2] = -1 + 0;
9732 #endif
9733
9734 #if 0
9735         zNear = r_refdef.nearclip;
9736         nudge = 1.0 - 1.0 / (1<<23);
9737         r_refdef.view.frustum[4].normal[0] = 0 - 0;
9738         r_refdef.view.frustum[4].normal[1] = 0 - 0;
9739         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
9740         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
9741         r_refdef.view.frustum[5].normal[0] = 0 + 0;
9742         r_refdef.view.frustum[5].normal[1] = 0 + 0;
9743         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
9744         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
9745 #endif
9746
9747
9748
9749 #if 0
9750         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
9751         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
9752         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
9753         r_refdef.view.frustum[0].dist = m[15] - m[12];
9754
9755         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
9756         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
9757         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
9758         r_refdef.view.frustum[1].dist = m[15] + m[12];
9759
9760         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
9761         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
9762         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
9763         r_refdef.view.frustum[2].dist = m[15] - m[13];
9764
9765         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
9766         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
9767         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
9768         r_refdef.view.frustum[3].dist = m[15] + m[13];
9769
9770         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
9771         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
9772         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
9773         r_refdef.view.frustum[4].dist = m[15] - m[14];
9774
9775         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
9776         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
9777         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
9778         r_refdef.view.frustum[5].dist = m[15] + m[14];
9779 #endif
9780
9781         if (r_refdef.view.useperspective)
9782         {
9783                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
9784                 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]);
9785                 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]);
9786                 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]);
9787                 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]);
9788
9789                 // then the normals from the corners relative to origin
9790                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
9791                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
9792                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
9793                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
9794
9795                 // in a NORMAL view, forward cross left == up
9796                 // in a REFLECTED view, forward cross left == down
9797                 // so our cross products above need to be adjusted for a left handed coordinate system
9798                 CrossProduct(forward, left, v);
9799                 if(DotProduct(v, up) < 0)
9800                 {
9801                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
9802                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
9803                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
9804                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
9805                 }
9806
9807                 // Leaving those out was a mistake, those were in the old code, and they
9808                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
9809                 // I couldn't reproduce it after adding those normalizations. --blub
9810                 VectorNormalize(r_refdef.view.frustum[0].normal);
9811                 VectorNormalize(r_refdef.view.frustum[1].normal);
9812                 VectorNormalize(r_refdef.view.frustum[2].normal);
9813                 VectorNormalize(r_refdef.view.frustum[3].normal);
9814
9815                 // make the corners absolute
9816                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
9817                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
9818                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
9819                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
9820
9821                 // one more normal
9822                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
9823
9824                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
9825                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
9826                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
9827                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
9828                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
9829         }
9830         else
9831         {
9832                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
9833                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
9834                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
9835                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
9836                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
9837                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
9838                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
9839                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
9840                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
9841                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
9842         }
9843         r_refdef.view.numfrustumplanes = 5;
9844
9845         if (r_refdef.view.useclipplane)
9846         {
9847                 r_refdef.view.numfrustumplanes = 6;
9848                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
9849         }
9850
9851         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
9852                 PlaneClassify(r_refdef.view.frustum + i);
9853
9854         // LordHavoc: note to all quake engine coders, Quake had a special case
9855         // for 90 degrees which assumed a square view (wrong), so I removed it,
9856         // Quake2 has it disabled as well.
9857
9858         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
9859         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
9860         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
9861         //PlaneClassify(&frustum[0]);
9862
9863         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
9864         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
9865         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
9866         //PlaneClassify(&frustum[1]);
9867
9868         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
9869         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
9870         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
9871         //PlaneClassify(&frustum[2]);
9872
9873         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
9874         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
9875         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
9876         //PlaneClassify(&frustum[3]);
9877
9878         // nearclip plane
9879         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
9880         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
9881         //PlaneClassify(&frustum[4]);
9882 }
9883
9884 void R_View_UpdateWithScissor(const int *myscissor)
9885 {
9886         R_Main_ResizeViewCache();
9887         R_View_SetFrustum(myscissor);
9888         R_View_WorldVisibility(r_refdef.view.useclipplane);
9889         R_View_UpdateEntityVisible();
9890         R_View_UpdateEntityLighting();
9891 }
9892
9893 void R_View_Update(void)
9894 {
9895         R_Main_ResizeViewCache();
9896         R_View_SetFrustum(NULL);
9897         R_View_WorldVisibility(r_refdef.view.useclipplane);
9898         R_View_UpdateEntityVisible();
9899         R_View_UpdateEntityLighting();
9900 }
9901
9902 void R_SetupView(qboolean allowwaterclippingplane)
9903 {
9904         const float *customclipplane = NULL;
9905         float plane[4];
9906         if (r_refdef.view.useclipplane && allowwaterclippingplane)
9907         {
9908                 // LordHavoc: couldn't figure out how to make this approach the
9909                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
9910                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
9911                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
9912                         dist = r_refdef.view.clipplane.dist;
9913                 plane[0] = r_refdef.view.clipplane.normal[0];
9914                 plane[1] = r_refdef.view.clipplane.normal[1];
9915                 plane[2] = r_refdef.view.clipplane.normal[2];
9916                 plane[3] = dist;
9917                 customclipplane = plane;
9918         }
9919
9920         if (!r_refdef.view.useperspective)
9921                 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);
9922         else if (vid.stencil && r_useinfinitefarclip.integer)
9923                 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);
9924         else
9925                 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);
9926         R_SetViewport(&r_refdef.view.viewport);
9927 }
9928
9929 void R_EntityMatrix(const matrix4x4_t *matrix)
9930 {
9931         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
9932         {
9933                 gl_modelmatrixchanged = false;
9934                 gl_modelmatrix = *matrix;
9935                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
9936                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
9937                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
9938                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
9939                 CHECKGLERROR
9940                 switch(vid.renderpath)
9941                 {
9942                 case RENDERPATH_D3D9:
9943 #ifdef SUPPORTD3D
9944                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
9945                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
9946 #endif
9947                         break;
9948                 case RENDERPATH_D3D10:
9949                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
9950                         break;
9951                 case RENDERPATH_D3D11:
9952                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
9953                         break;
9954                 case RENDERPATH_GL20:
9955                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
9956                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
9957                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
9958                         break;
9959                 case RENDERPATH_CGGL:
9960 #ifdef SUPPORTCG
9961                         CHECKCGERROR
9962                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
9963                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
9964                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
9965 #endif
9966                         break;
9967                 case RENDERPATH_GL13:
9968                 case RENDERPATH_GL11:
9969                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
9970                         break;
9971                 case RENDERPATH_SOFT:
9972                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
9973                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
9974                         break;
9975                 case RENDERPATH_GLES2:
9976                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
9977                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
9978                         break;
9979                 }
9980         }
9981 }
9982
9983 void R_ResetViewRendering2D(void)
9984 {
9985         r_viewport_t viewport;
9986         DrawQ_Finish();
9987
9988         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
9989         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);
9990         R_SetViewport(&viewport);
9991         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
9992         GL_Color(1, 1, 1, 1);
9993         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9994         GL_BlendFunc(GL_ONE, GL_ZERO);
9995         GL_AlphaTest(false);
9996         GL_ScissorTest(false);
9997         GL_DepthMask(false);
9998         GL_DepthRange(0, 1);
9999         GL_DepthTest(false);
10000         GL_DepthFunc(GL_LEQUAL);
10001         R_EntityMatrix(&identitymatrix);
10002         R_Mesh_ResetTextureState();
10003         GL_PolygonOffset(0, 0);
10004         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
10005         switch(vid.renderpath)
10006         {
10007         case RENDERPATH_GL11:
10008         case RENDERPATH_GL13:
10009         case RENDERPATH_GL20:
10010         case RENDERPATH_CGGL:
10011         case RENDERPATH_GLES2:
10012                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
10013                 break;
10014         case RENDERPATH_D3D9:
10015         case RENDERPATH_D3D10:
10016         case RENDERPATH_D3D11:
10017         case RENDERPATH_SOFT:
10018                 break;
10019         }
10020         GL_CullFace(GL_NONE);
10021 }
10022
10023 void R_ResetViewRendering3D(void)
10024 {
10025         DrawQ_Finish();
10026
10027         R_SetupView(true);
10028         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
10029         GL_Color(1, 1, 1, 1);
10030         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10031         GL_BlendFunc(GL_ONE, GL_ZERO);
10032         GL_AlphaTest(false);
10033         GL_ScissorTest(true);
10034         GL_DepthMask(true);
10035         GL_DepthRange(0, 1);
10036         GL_DepthTest(true);
10037         GL_DepthFunc(GL_LEQUAL);
10038         R_EntityMatrix(&identitymatrix);
10039         R_Mesh_ResetTextureState();
10040         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10041         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
10042         switch(vid.renderpath)
10043         {
10044         case RENDERPATH_GL11:
10045         case RENDERPATH_GL13:
10046         case RENDERPATH_GL20:
10047         case RENDERPATH_CGGL:
10048         case RENDERPATH_GLES2:
10049                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
10050                 break;
10051         case RENDERPATH_D3D9:
10052         case RENDERPATH_D3D10:
10053         case RENDERPATH_D3D11:
10054         case RENDERPATH_SOFT:
10055                 break;
10056         }
10057         GL_CullFace(r_refdef.view.cullface_back);
10058 }
10059
10060 /*
10061 ================
10062 R_RenderView_UpdateViewVectors
10063 ================
10064 */
10065 static void R_RenderView_UpdateViewVectors(void)
10066 {
10067         // break apart the view matrix into vectors for various purposes
10068         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
10069         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
10070         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
10071         VectorNegate(r_refdef.view.left, r_refdef.view.right);
10072         // make an inverted copy of the view matrix for tracking sprites
10073         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
10074 }
10075
10076 void R_RenderScene(void);
10077 void R_RenderWaterPlanes(void);
10078
10079 static void R_Water_StartFrame(void)
10080 {
10081         int i;
10082         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
10083         r_waterstate_waterplane_t *p;
10084
10085         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
10086                 return;
10087
10088         switch(vid.renderpath)
10089         {
10090         case RENDERPATH_GL20:
10091         case RENDERPATH_CGGL:
10092         case RENDERPATH_D3D9:
10093         case RENDERPATH_D3D10:
10094         case RENDERPATH_D3D11:
10095         case RENDERPATH_SOFT:
10096                 break;
10097         case RENDERPATH_GL13:
10098         case RENDERPATH_GL11:
10099         case RENDERPATH_GLES2:
10100                 return;
10101         }
10102
10103         // set waterwidth and waterheight to the water resolution that will be
10104         // used (often less than the screen resolution for faster rendering)
10105         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
10106         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
10107
10108         // calculate desired texture sizes
10109         // can't use water if the card does not support the texture size
10110         if (!r_water.integer || r_showsurfaces.integer)
10111                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
10112         else if (vid.support.arb_texture_non_power_of_two)
10113         {
10114                 texturewidth = waterwidth;
10115                 textureheight = waterheight;
10116                 camerawidth = waterwidth;
10117                 cameraheight = waterheight;
10118         }
10119         else
10120         {
10121                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
10122                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
10123                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
10124                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
10125         }
10126
10127         // allocate textures as needed
10128         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
10129         {
10130                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
10131                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
10132                 {
10133                         if (p->texture_refraction)
10134                                 R_FreeTexture(p->texture_refraction);
10135                         p->texture_refraction = NULL;
10136                         if (p->texture_reflection)
10137                                 R_FreeTexture(p->texture_reflection);
10138                         p->texture_reflection = NULL;
10139                         if (p->texture_camera)
10140                                 R_FreeTexture(p->texture_camera);
10141                         p->texture_camera = NULL;
10142                 }
10143                 memset(&r_waterstate, 0, sizeof(r_waterstate));
10144                 r_waterstate.texturewidth = texturewidth;
10145                 r_waterstate.textureheight = textureheight;
10146                 r_waterstate.camerawidth = camerawidth;
10147                 r_waterstate.cameraheight = cameraheight;
10148         }
10149
10150         if (r_waterstate.texturewidth)
10151         {
10152                 r_waterstate.enabled = true;
10153
10154                 // when doing a reduced render (HDR) we want to use a smaller area
10155                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
10156                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
10157
10158                 // set up variables that will be used in shader setup
10159                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
10160                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
10161                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
10162                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
10163         }
10164
10165         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
10166         r_waterstate.numwaterplanes = 0;
10167 }
10168
10169 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
10170 {
10171         int triangleindex, planeindex;
10172         const int *e;
10173         vec3_t vert[3];
10174         vec3_t normal;
10175         vec3_t center;
10176         mplane_t plane;
10177         r_waterstate_waterplane_t *p;
10178         texture_t *t = R_GetCurrentTexture(surface->texture);
10179
10180         // just use the first triangle with a valid normal for any decisions
10181         VectorClear(normal);
10182         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
10183         {
10184                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
10185                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
10186                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
10187                 TriangleNormal(vert[0], vert[1], vert[2], normal);
10188                 if (VectorLength2(normal) >= 0.001)
10189                         break;
10190         }
10191
10192         VectorCopy(normal, plane.normal);
10193         VectorNormalize(plane.normal);
10194         plane.dist = DotProduct(vert[0], plane.normal);
10195         PlaneClassify(&plane);
10196         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
10197         {
10198                 // skip backfaces (except if nocullface is set)
10199                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
10200                         return;
10201                 VectorNegate(plane.normal, plane.normal);
10202                 plane.dist *= -1;
10203                 PlaneClassify(&plane);
10204         }
10205
10206
10207         // find a matching plane if there is one
10208         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10209                 if(p->camera_entity == t->camera_entity)
10210                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
10211                                 break;
10212         if (planeindex >= r_waterstate.maxwaterplanes)
10213                 return; // nothing we can do, out of planes
10214
10215         // if this triangle does not fit any known plane rendered this frame, add one
10216         if (planeindex >= r_waterstate.numwaterplanes)
10217         {
10218                 // store the new plane
10219                 r_waterstate.numwaterplanes++;
10220                 p->plane = plane;
10221                 // clear materialflags and pvs
10222                 p->materialflags = 0;
10223                 p->pvsvalid = false;
10224                 p->camera_entity = t->camera_entity;
10225                 VectorCopy(surface->mins, p->mins);
10226                 VectorCopy(surface->maxs, p->maxs);
10227         }
10228         else
10229         {
10230                 // merge mins/maxs
10231                 p->mins[0] = min(p->mins[0], surface->mins[0]);
10232                 p->mins[1] = min(p->mins[1], surface->mins[1]);
10233                 p->mins[2] = min(p->mins[2], surface->mins[2]);
10234                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
10235                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
10236                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
10237         }
10238         // merge this surface's materialflags into the waterplane
10239         p->materialflags |= t->currentmaterialflags;
10240         if(!(p->materialflags & MATERIALFLAG_CAMERA))
10241         {
10242                 // merge this surface's PVS into the waterplane
10243                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
10244                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
10245                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
10246                 {
10247                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
10248                         p->pvsvalid = true;
10249                 }
10250         }
10251 }
10252
10253 static void R_Water_ProcessPlanes(void)
10254 {
10255         int myscissor[4];
10256         r_refdef_view_t originalview;
10257         r_refdef_view_t myview;
10258         int planeindex;
10259         r_waterstate_waterplane_t *p;
10260         vec3_t visorigin;
10261
10262         originalview = r_refdef.view;
10263
10264         // make sure enough textures are allocated
10265         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10266         {
10267                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10268                 {
10269                         if (!p->texture_refraction)
10270                                 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);
10271                         if (!p->texture_refraction)
10272                                 goto error;
10273                 }
10274                 else if (p->materialflags & MATERIALFLAG_CAMERA)
10275                 {
10276                         if (!p->texture_camera)
10277                                 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);
10278                         if (!p->texture_camera)
10279                                 goto error;
10280                 }
10281
10282                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
10283                 {
10284                         if (!p->texture_reflection)
10285                                 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);
10286                         if (!p->texture_reflection)
10287                                 goto error;
10288                 }
10289         }
10290
10291         // render views
10292         r_refdef.view = originalview;
10293         r_refdef.view.showdebug = false;
10294         r_refdef.view.width = r_waterstate.waterwidth;
10295         r_refdef.view.height = r_waterstate.waterheight;
10296         r_refdef.view.useclipplane = true;
10297         myview = r_refdef.view;
10298         r_waterstate.renderingscene = true;
10299         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10300         {
10301                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
10302                 {
10303                         r_refdef.view = myview;
10304                         if(r_water_scissormode.integer)
10305                         {
10306                                 R_SetupView(true);
10307                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
10308                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
10309                         }
10310
10311                         // render reflected scene and copy into texture
10312                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
10313                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
10314                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
10315                         r_refdef.view.clipplane = p->plane;
10316
10317                         // reverse the cullface settings for this render
10318                         r_refdef.view.cullface_front = GL_FRONT;
10319                         r_refdef.view.cullface_back = GL_BACK;
10320                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
10321                         {
10322                                 r_refdef.view.usecustompvs = true;
10323                                 if (p->pvsvalid)
10324                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
10325                                 else
10326                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
10327                         }
10328
10329                         R_ResetViewRendering3D();
10330                         R_ClearScreen(r_refdef.fogenabled);
10331                         if(r_water_scissormode.integer & 2)
10332                                 R_View_UpdateWithScissor(myscissor);
10333                         else
10334                                 R_View_Update();
10335                         if(r_water_scissormode.integer & 1)
10336                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
10337                         R_RenderScene();
10338
10339                         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);
10340                 }
10341
10342                 // render the normal view scene and copy into texture
10343                 // (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)
10344                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10345                 {
10346                         r_refdef.view = myview;
10347                         if(r_water_scissormode.integer)
10348                         {
10349                                 R_SetupView(true);
10350                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
10351                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
10352                         }
10353
10354                         r_waterstate.renderingrefraction = true;
10355
10356                         r_refdef.view.clipplane = p->plane;
10357                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
10358                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
10359
10360                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
10361                         {
10362                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
10363                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
10364                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
10365                                 R_RenderView_UpdateViewVectors();
10366                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
10367                                 {
10368                                         r_refdef.view.usecustompvs = true;
10369                                         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);
10370                                 }
10371                         }
10372
10373                         PlaneClassify(&r_refdef.view.clipplane);
10374
10375                         R_ResetViewRendering3D();
10376                         R_ClearScreen(r_refdef.fogenabled);
10377                         if(r_water_scissormode.integer & 2)
10378                                 R_View_UpdateWithScissor(myscissor);
10379                         else
10380                                 R_View_Update();
10381                         if(r_water_scissormode.integer & 1)
10382                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
10383                         R_RenderScene();
10384
10385                         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);
10386                         r_waterstate.renderingrefraction = false;
10387                 }
10388                 else if (p->materialflags & MATERIALFLAG_CAMERA)
10389                 {
10390                         r_refdef.view = myview;
10391
10392                         r_refdef.view.clipplane = p->plane;
10393                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
10394                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
10395
10396                         r_refdef.view.width = r_waterstate.camerawidth;
10397                         r_refdef.view.height = r_waterstate.cameraheight;
10398                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
10399                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
10400
10401                         if(p->camera_entity)
10402                         {
10403                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
10404                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
10405                         }
10406
10407                         // note: all of the view is used for displaying... so
10408                         // there is no use in scissoring
10409
10410                         // reverse the cullface settings for this render
10411                         r_refdef.view.cullface_front = GL_FRONT;
10412                         r_refdef.view.cullface_back = GL_BACK;
10413                         // also reverse the view matrix
10414                         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
10415                         R_RenderView_UpdateViewVectors();
10416                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
10417                         {
10418                                 r_refdef.view.usecustompvs = true;
10419                                 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);
10420                         }
10421                         
10422                         // camera needs no clipplane
10423                         r_refdef.view.useclipplane = false;
10424
10425                         PlaneClassify(&r_refdef.view.clipplane);
10426
10427                         R_ResetViewRendering3D();
10428                         R_ClearScreen(r_refdef.fogenabled);
10429                         R_View_Update();
10430                         R_RenderScene();
10431
10432                         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);
10433                         r_waterstate.renderingrefraction = false;
10434                 }
10435
10436         }
10437         r_waterstate.renderingscene = false;
10438         r_refdef.view = originalview;
10439         R_ResetViewRendering3D();
10440         R_ClearScreen(r_refdef.fogenabled);
10441         R_View_Update();
10442         return;
10443 error:
10444         r_refdef.view = originalview;
10445         r_waterstate.renderingscene = false;
10446         Cvar_SetValueQuick(&r_water, 0);
10447         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
10448         return;
10449 }
10450
10451 void R_Bloom_StartFrame(void)
10452 {
10453         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
10454
10455         switch(vid.renderpath)
10456         {
10457         case RENDERPATH_GL20:
10458         case RENDERPATH_CGGL:
10459         case RENDERPATH_D3D9:
10460         case RENDERPATH_D3D10:
10461         case RENDERPATH_D3D11:
10462         case RENDERPATH_SOFT:
10463                 break;
10464         case RENDERPATH_GL13:
10465         case RENDERPATH_GL11:
10466         case RENDERPATH_GLES2:
10467                 return;
10468         }
10469
10470         // set bloomwidth and bloomheight to the bloom resolution that will be
10471         // used (often less than the screen resolution for faster rendering)
10472         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
10473         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
10474         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
10475         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
10476         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
10477
10478         // calculate desired texture sizes
10479         if (vid.support.arb_texture_non_power_of_two)
10480         {
10481                 screentexturewidth = r_refdef.view.width;
10482                 screentextureheight = r_refdef.view.height;
10483                 bloomtexturewidth = r_bloomstate.bloomwidth;
10484                 bloomtextureheight = r_bloomstate.bloomheight;
10485         }
10486         else
10487         {
10488                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
10489                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
10490                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
10491                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
10492         }
10493
10494         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))
10495         {
10496                 Cvar_SetValueQuick(&r_hdr, 0);
10497                 Cvar_SetValueQuick(&r_bloom, 0);
10498                 Cvar_SetValueQuick(&r_motionblur, 0);
10499                 Cvar_SetValueQuick(&r_damageblur, 0);
10500         }
10501
10502         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)))
10503                 screentexturewidth = screentextureheight = 0;
10504         if (!r_hdr.integer && !r_bloom.integer)
10505                 bloomtexturewidth = bloomtextureheight = 0;
10506
10507         // allocate textures as needed
10508         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
10509         {
10510                 if (r_bloomstate.texture_screen)
10511                         R_FreeTexture(r_bloomstate.texture_screen);
10512                 r_bloomstate.texture_screen = NULL;
10513                 r_bloomstate.screentexturewidth = screentexturewidth;
10514                 r_bloomstate.screentextureheight = screentextureheight;
10515                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
10516                         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);
10517         }
10518         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
10519         {
10520                 if (r_bloomstate.texture_bloom)
10521                         R_FreeTexture(r_bloomstate.texture_bloom);
10522                 r_bloomstate.texture_bloom = NULL;
10523                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
10524                 r_bloomstate.bloomtextureheight = bloomtextureheight;
10525                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
10526                         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);
10527         }
10528
10529         // when doing a reduced render (HDR) we want to use a smaller area
10530         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
10531         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
10532         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
10533         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
10534         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
10535
10536         // set up a texcoord array for the full resolution screen image
10537         // (we have to keep this around to copy back during final render)
10538         r_bloomstate.screentexcoord2f[0] = 0;
10539         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
10540         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
10541         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
10542         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
10543         r_bloomstate.screentexcoord2f[5] = 0;
10544         r_bloomstate.screentexcoord2f[6] = 0;
10545         r_bloomstate.screentexcoord2f[7] = 0;
10546
10547         // set up a texcoord array for the reduced resolution bloom image
10548         // (which will be additive blended over the screen image)
10549         r_bloomstate.bloomtexcoord2f[0] = 0;
10550         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
10551         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
10552         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
10553         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
10554         r_bloomstate.bloomtexcoord2f[5] = 0;
10555         r_bloomstate.bloomtexcoord2f[6] = 0;
10556         r_bloomstate.bloomtexcoord2f[7] = 0;
10557
10558         switch(vid.renderpath)
10559         {
10560         case RENDERPATH_GL11:
10561         case RENDERPATH_GL13:
10562         case RENDERPATH_GL20:
10563         case RENDERPATH_CGGL:
10564         case RENDERPATH_SOFT:
10565         case RENDERPATH_GLES2:
10566                 break;
10567         case RENDERPATH_D3D9:
10568         case RENDERPATH_D3D10:
10569         case RENDERPATH_D3D11:
10570                 {
10571                         int i;
10572                         for (i = 0;i < 4;i++)
10573                         {
10574                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
10575                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
10576                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
10577                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
10578                         }
10579                 }
10580                 break;
10581         }
10582
10583         if (r_hdr.integer || r_bloom.integer)
10584         {
10585                 r_bloomstate.enabled = true;
10586                 r_bloomstate.hdr = r_hdr.integer != 0;
10587         }
10588
10589         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);
10590 }
10591
10592 void R_Bloom_CopyBloomTexture(float colorscale)
10593 {
10594         r_refdef.stats.bloom++;
10595
10596         // scale down screen texture to the bloom texture size
10597         CHECKGLERROR
10598         R_SetViewport(&r_bloomstate.viewport);
10599         GL_BlendFunc(GL_ONE, GL_ZERO);
10600         GL_Color(colorscale, colorscale, colorscale, 1);
10601         // 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...
10602         switch(vid.renderpath)
10603         {
10604         case RENDERPATH_GL11:
10605         case RENDERPATH_GL13:
10606         case RENDERPATH_GL20:
10607         case RENDERPATH_CGGL:
10608         case RENDERPATH_SOFT:
10609         case RENDERPATH_GLES2:
10610                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
10611                 break;
10612         case RENDERPATH_D3D9:
10613         case RENDERPATH_D3D10:
10614         case RENDERPATH_D3D11:
10615                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
10616                 break;
10617         }
10618         // TODO: do boxfilter scale-down in shader?
10619         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
10620         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10621         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
10622
10623         // we now have a bloom image in the framebuffer
10624         // copy it into the bloom image texture for later processing
10625         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);
10626         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
10627 }
10628
10629 void R_Bloom_CopyHDRTexture(void)
10630 {
10631         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);
10632         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
10633 }
10634
10635 void R_Bloom_MakeTexture(void)
10636 {
10637         int x, range, dir;
10638         float xoffset, yoffset, r, brighten;
10639
10640         r_refdef.stats.bloom++;
10641
10642         R_ResetViewRendering2D();
10643
10644         // we have a bloom image in the framebuffer
10645         CHECKGLERROR
10646         R_SetViewport(&r_bloomstate.viewport);
10647
10648         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
10649         {
10650                 x *= 2;
10651                 r = bound(0, r_bloom_colorexponent.value / x, 1);
10652                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10653                 GL_Color(r,r,r,1);
10654                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
10655                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
10656                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10657                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
10658
10659                 // copy the vertically blurred bloom view to a texture
10660                 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);
10661                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
10662         }
10663
10664         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
10665         brighten = r_bloom_brighten.value;
10666         if (r_hdr.integer)
10667                 brighten *= r_hdr_range.value;
10668         brighten = sqrt(brighten);
10669         if(range >= 1)
10670                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
10671         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
10672
10673         for (dir = 0;dir < 2;dir++)
10674         {
10675                 // blend on at multiple vertical offsets to achieve a vertical blur
10676                 // TODO: do offset blends using GLSL
10677                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
10678                 GL_BlendFunc(GL_ONE, GL_ZERO);
10679                 for (x = -range;x <= range;x++)
10680                 {
10681                         if (!dir){xoffset = 0;yoffset = x;}
10682                         else {xoffset = x;yoffset = 0;}
10683                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
10684                         yoffset /= (float)r_bloomstate.bloomtextureheight;
10685                         // compute a texcoord array with the specified x and y offset
10686                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
10687                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
10688                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
10689                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
10690                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
10691                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
10692                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
10693                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
10694                         // this r value looks like a 'dot' particle, fading sharply to
10695                         // black at the edges
10696                         // (probably not realistic but looks good enough)
10697                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
10698                         //r = brighten/(range*2+1);
10699                         r = brighten / (range * 2 + 1);
10700                         if(range >= 1)
10701                                 r *= (1 - x*x/(float)(range*range));
10702                         GL_Color(r, r, r, 1);
10703                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
10704                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10705                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
10706                         GL_BlendFunc(GL_ONE, GL_ONE);
10707                 }
10708
10709                 // copy the vertically blurred bloom view to a texture
10710                 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);
10711                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
10712         }
10713 }
10714
10715 void R_HDR_RenderBloomTexture(void)
10716 {
10717         int oldwidth, oldheight;
10718         float oldcolorscale;
10719         qboolean oldwaterstate;
10720
10721         oldwaterstate = r_waterstate.enabled;
10722         oldcolorscale = r_refdef.view.colorscale;
10723         oldwidth = r_refdef.view.width;
10724         oldheight = r_refdef.view.height;
10725         r_refdef.view.width = r_bloomstate.bloomwidth;
10726         r_refdef.view.height = r_bloomstate.bloomheight;
10727
10728         if(r_hdr.integer < 2)
10729                 r_waterstate.enabled = false;
10730
10731         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
10732         // TODO: add exposure compensation features
10733         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
10734
10735         r_refdef.view.showdebug = false;
10736         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
10737
10738         R_ResetViewRendering3D();
10739
10740         R_ClearScreen(r_refdef.fogenabled);
10741         if (r_timereport_active)
10742                 R_TimeReport("HDRclear");
10743
10744         R_View_Update();
10745         if (r_timereport_active)
10746                 R_TimeReport("visibility");
10747
10748         // only do secondary renders with HDR if r_hdr is 2 or higher
10749         r_waterstate.numwaterplanes = 0;
10750         if (r_waterstate.enabled)
10751                 R_RenderWaterPlanes();
10752
10753         r_refdef.view.showdebug = true;
10754         R_RenderScene();
10755         r_waterstate.numwaterplanes = 0;
10756
10757         R_ResetViewRendering2D();
10758
10759         R_Bloom_CopyHDRTexture();
10760         R_Bloom_MakeTexture();
10761
10762         // restore the view settings
10763         r_waterstate.enabled = oldwaterstate;
10764         r_refdef.view.width = oldwidth;
10765         r_refdef.view.height = oldheight;
10766         r_refdef.view.colorscale = oldcolorscale;
10767
10768         R_ResetViewRendering3D();
10769
10770         R_ClearScreen(r_refdef.fogenabled);
10771         if (r_timereport_active)
10772                 R_TimeReport("viewclear");
10773 }
10774
10775 static void R_BlendView(void)
10776 {
10777         unsigned int permutation;
10778         float uservecs[4][4];
10779
10780         switch (vid.renderpath)
10781         {
10782         case RENDERPATH_GL20:
10783         case RENDERPATH_CGGL:
10784         case RENDERPATH_D3D9:
10785         case RENDERPATH_D3D10:
10786         case RENDERPATH_D3D11:
10787         case RENDERPATH_SOFT:
10788         case RENDERPATH_GLES2:
10789                 permutation =
10790                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
10791                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
10792                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
10793                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
10794                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
10795
10796                 if (r_bloomstate.texture_screen)
10797                 {
10798                         // make sure the buffer is available
10799                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
10800
10801                         R_ResetViewRendering2D();
10802
10803                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
10804                         {
10805                                 // declare variables
10806                                 float speed;
10807                                 static float avgspeed;
10808
10809                                 speed = VectorLength(cl.movement_velocity);
10810
10811                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
10812                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
10813
10814                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
10815                                 speed = bound(0, speed, 1);
10816                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
10817
10818                                 // calculate values into a standard alpha
10819                                 cl.motionbluralpha = 1 - exp(-
10820                                                 (
10821                                                  (r_motionblur.value * speed / 80)
10822                                                  +
10823                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
10824                                                 )
10825                                                 /
10826                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
10827                                            );
10828
10829                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
10830                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
10831                                 // apply the blur
10832                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
10833                                 {
10834                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10835                                         GL_Color(1, 1, 1, cl.motionbluralpha);
10836                                         switch(vid.renderpath)
10837                                         {
10838                                         case RENDERPATH_GL11:
10839                                         case RENDERPATH_GL13:
10840                                         case RENDERPATH_GL20:
10841                                         case RENDERPATH_CGGL:
10842                                         case RENDERPATH_SOFT:
10843                                         case RENDERPATH_GLES2:
10844                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
10845                                                 break;
10846                                         case RENDERPATH_D3D9:
10847                                         case RENDERPATH_D3D10:
10848                                         case RENDERPATH_D3D11:
10849                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
10850                                                 break;
10851                                         }
10852                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
10853                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10854                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
10855                                 }
10856                         }
10857
10858                         // copy view into the screen texture
10859                         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);
10860                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
10861                 }
10862                 else if (!r_bloomstate.texture_bloom)
10863                 {
10864                         // we may still have to do view tint...
10865                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
10866                         {
10867                                 // apply a color tint to the whole view
10868                                 R_ResetViewRendering2D();
10869                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
10870                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
10871                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10872                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10873                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10874                         }
10875                         break; // no screen processing, no bloom, skip it
10876                 }
10877
10878                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
10879                 {
10880                         // render simple bloom effect
10881                         // copy the screen and shrink it and darken it for the bloom process
10882                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
10883                         // make the bloom texture
10884                         R_Bloom_MakeTexture();
10885                 }
10886
10887 #if _MSC_VER >= 1400
10888 #define sscanf sscanf_s
10889 #endif
10890                 memset(uservecs, 0, sizeof(uservecs));
10891                 if (r_glsl_postprocess_uservec1_enable.integer)
10892                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
10893                 if (r_glsl_postprocess_uservec2_enable.integer)
10894                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
10895                 if (r_glsl_postprocess_uservec3_enable.integer)
10896                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
10897                 if (r_glsl_postprocess_uservec4_enable.integer)
10898                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
10899
10900                 R_ResetViewRendering2D();
10901                 GL_Color(1, 1, 1, 1);
10902                 GL_BlendFunc(GL_ONE, GL_ZERO);
10903
10904                 switch(vid.renderpath)
10905                 {
10906                 case RENDERPATH_GL20:
10907                 case RENDERPATH_GLES2:
10908                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
10909                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
10910                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
10911                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
10912                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
10913                         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]);
10914                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
10915                         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]);
10916                         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]);
10917                         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]);
10918                         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]);
10919                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
10920                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
10921                         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);
10922                         break;
10923                 case RENDERPATH_CGGL:
10924 #ifdef SUPPORTCG
10925                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
10926                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
10927                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
10928                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
10929                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
10930                         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
10931                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
10932                         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
10933                         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
10934                         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
10935                         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
10936                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
10937                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
10938                         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);
10939 #endif
10940                         break;
10941                 case RENDERPATH_D3D9:
10942 #ifdef SUPPORTD3D
10943                         // 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...
10944                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
10945                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
10946                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
10947                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
10948                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
10949                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
10950                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
10951                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
10952                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
10953                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
10954                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
10955                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
10956                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
10957                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
10958 #endif
10959                         break;
10960                 case RENDERPATH_D3D10:
10961                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10962                         break;
10963                 case RENDERPATH_D3D11:
10964                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10965                         break;
10966                 case RENDERPATH_SOFT:
10967                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
10968                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
10969                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
10970                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
10971                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
10972                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
10973                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
10974                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
10975                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
10976                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
10977                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
10978                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
10979                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
10980                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
10981                         break;
10982                 default:
10983                         break;
10984                 }
10985                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10986                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
10987                 break;
10988         case RENDERPATH_GL13:
10989         case RENDERPATH_GL11:
10990                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
10991                 {
10992                         // apply a color tint to the whole view
10993                         R_ResetViewRendering2D();
10994                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
10995                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
10996                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10997                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10998                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10999                 }
11000                 break;
11001         }
11002 }
11003
11004 matrix4x4_t r_waterscrollmatrix;
11005
11006 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
11007 {
11008         if (r_refdef.fog_density)
11009         {
11010                 r_refdef.fogcolor[0] = r_refdef.fog_red;
11011                 r_refdef.fogcolor[1] = r_refdef.fog_green;
11012                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
11013
11014                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
11015                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
11016                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
11017                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
11018
11019                 {
11020                         vec3_t fogvec;
11021                         VectorCopy(r_refdef.fogcolor, fogvec);
11022                         //   color.rgb *= ContrastBoost * SceneBrightness;
11023                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
11024                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
11025                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
11026                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
11027                 }
11028         }
11029 }
11030
11031 void R_UpdateVariables(void)
11032 {
11033         R_Textures_Frame();
11034
11035         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
11036
11037         r_refdef.farclip = r_farclip_base.value;
11038         if (r_refdef.scene.worldmodel)
11039                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
11040         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
11041
11042         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
11043                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
11044         r_refdef.polygonfactor = 0;
11045         r_refdef.polygonoffset = 0;
11046         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
11047         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
11048
11049         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
11050         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
11051         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
11052         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
11053         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
11054         if (FAKELIGHT_ENABLED)
11055         {
11056                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
11057         }
11058         if (r_showsurfaces.integer)
11059         {
11060                 r_refdef.scene.rtworld = false;
11061                 r_refdef.scene.rtworldshadows = false;
11062                 r_refdef.scene.rtdlight = false;
11063                 r_refdef.scene.rtdlightshadows = false;
11064                 r_refdef.lightmapintensity = 0;
11065         }
11066
11067         if (gamemode == GAME_NEHAHRA)
11068         {
11069                 if (gl_fogenable.integer)
11070                 {
11071                         r_refdef.oldgl_fogenable = true;
11072                         r_refdef.fog_density = gl_fogdensity.value;
11073                         r_refdef.fog_red = gl_fogred.value;
11074                         r_refdef.fog_green = gl_foggreen.value;
11075                         r_refdef.fog_blue = gl_fogblue.value;
11076                         r_refdef.fog_alpha = 1;
11077                         r_refdef.fog_start = 0;
11078                         r_refdef.fog_end = gl_skyclip.value;
11079                         r_refdef.fog_height = 1<<30;
11080                         r_refdef.fog_fadedepth = 128;
11081                 }
11082                 else if (r_refdef.oldgl_fogenable)
11083                 {
11084                         r_refdef.oldgl_fogenable = false;
11085                         r_refdef.fog_density = 0;
11086                         r_refdef.fog_red = 0;
11087                         r_refdef.fog_green = 0;
11088                         r_refdef.fog_blue = 0;
11089                         r_refdef.fog_alpha = 0;
11090                         r_refdef.fog_start = 0;
11091                         r_refdef.fog_end = 0;
11092                         r_refdef.fog_height = 1<<30;
11093                         r_refdef.fog_fadedepth = 128;
11094                 }
11095         }
11096
11097         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
11098         r_refdef.fog_start = max(0, r_refdef.fog_start);
11099         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
11100
11101         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
11102
11103         if (r_refdef.fog_density && r_drawfog.integer)
11104         {
11105                 r_refdef.fogenabled = true;
11106                 // this is the point where the fog reaches 0.9986 alpha, which we
11107                 // consider a good enough cutoff point for the texture
11108                 // (0.9986 * 256 == 255.6)
11109                 if (r_fog_exp2.integer)
11110                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
11111                 else
11112                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
11113                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
11114                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
11115                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
11116                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
11117                         R_BuildFogHeightTexture();
11118                 // fog color was already set
11119                 // update the fog texture
11120                 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)
11121                         R_BuildFogTexture();
11122                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
11123                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
11124         }
11125         else
11126                 r_refdef.fogenabled = false;
11127
11128         switch(vid.renderpath)
11129         {
11130         case RENDERPATH_GL20:
11131         case RENDERPATH_CGGL:
11132         case RENDERPATH_D3D9:
11133         case RENDERPATH_D3D10:
11134         case RENDERPATH_D3D11:
11135         case RENDERPATH_SOFT:
11136         case RENDERPATH_GLES2:
11137                 if(v_glslgamma.integer && !vid_gammatables_trivial)
11138                 {
11139                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
11140                         {
11141                                 // build GLSL gamma texture
11142 #define RAMPWIDTH 256
11143                                 unsigned short ramp[RAMPWIDTH * 3];
11144                                 unsigned char rampbgr[RAMPWIDTH][4];
11145                                 int i;
11146
11147                                 r_texture_gammaramps_serial = vid_gammatables_serial;
11148
11149                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
11150                                 for(i = 0; i < RAMPWIDTH; ++i)
11151                                 {
11152                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
11153                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
11154                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
11155                                         rampbgr[i][3] = 0;
11156                                 }
11157                                 if (r_texture_gammaramps)
11158                                 {
11159                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
11160                                 }
11161                                 else
11162                                 {
11163                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
11164                                 }
11165                         }
11166                 }
11167                 else
11168                 {
11169                         // remove GLSL gamma texture
11170                 }
11171                 break;
11172         case RENDERPATH_GL13:
11173         case RENDERPATH_GL11:
11174                 break;
11175         }
11176 }
11177
11178 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
11179 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
11180 /*
11181 ================
11182 R_SelectScene
11183 ================
11184 */
11185 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
11186         if( scenetype != r_currentscenetype ) {
11187                 // store the old scenetype
11188                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
11189                 r_currentscenetype = scenetype;
11190                 // move in the new scene
11191                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
11192         }
11193 }
11194
11195 /*
11196 ================
11197 R_GetScenePointer
11198 ================
11199 */
11200 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
11201 {
11202         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
11203         if( scenetype == r_currentscenetype ) {
11204                 return &r_refdef.scene;
11205         } else {
11206                 return &r_scenes_store[ scenetype ];
11207         }
11208 }
11209
11210 /*
11211 ================
11212 R_RenderView
11213 ================
11214 */
11215 int dpsoftrast_test;
11216 void R_RenderView(void)
11217 {
11218         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
11219
11220         dpsoftrast_test = r_test.integer;
11221
11222         if (r_timereport_active)
11223                 R_TimeReport("start");
11224         r_textureframe++; // used only by R_GetCurrentTexture
11225         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11226
11227         if(R_CompileShader_CheckStaticParms())
11228                 R_GLSL_Restart_f();
11229
11230         if (!r_drawentities.integer)
11231                 r_refdef.scene.numentities = 0;
11232
11233         R_AnimCache_ClearCache();
11234         R_FrameData_NewFrame();
11235
11236         /* adjust for stereo display */
11237         if(R_Stereo_Active())
11238         {
11239                 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);
11240                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
11241         }
11242
11243         if (r_refdef.view.isoverlay)
11244         {
11245                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
11246                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
11247                 R_TimeReport("depthclear");
11248
11249                 r_refdef.view.showdebug = false;
11250
11251                 r_waterstate.enabled = false;
11252                 r_waterstate.numwaterplanes = 0;
11253
11254                 R_RenderScene();
11255
11256                 r_refdef.view.matrix = originalmatrix;
11257
11258                 CHECKGLERROR
11259                 return;
11260         }
11261
11262         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
11263         {
11264                 r_refdef.view.matrix = originalmatrix;
11265                 return; //Host_Error ("R_RenderView: NULL worldmodel");
11266         }
11267
11268         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
11269
11270         R_RenderView_UpdateViewVectors();
11271
11272         R_Shadow_UpdateWorldLightSelection();
11273
11274         R_Bloom_StartFrame();
11275         R_Water_StartFrame();
11276
11277         CHECKGLERROR
11278         if (r_timereport_active)
11279                 R_TimeReport("viewsetup");
11280
11281         R_ResetViewRendering3D();
11282
11283         if (r_refdef.view.clear || r_refdef.fogenabled)
11284         {
11285                 R_ClearScreen(r_refdef.fogenabled);
11286                 if (r_timereport_active)
11287                         R_TimeReport("viewclear");
11288         }
11289         r_refdef.view.clear = true;
11290
11291         // this produces a bloom texture to be used in R_BlendView() later
11292         if (r_hdr.integer && r_bloomstate.bloomwidth)
11293         {
11294                 R_HDR_RenderBloomTexture();
11295                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
11296                 r_textureframe++; // used only by R_GetCurrentTexture
11297         }
11298
11299         r_refdef.view.showdebug = true;
11300
11301         R_View_Update();
11302         if (r_timereport_active)
11303                 R_TimeReport("visibility");
11304
11305         r_waterstate.numwaterplanes = 0;
11306         if (r_waterstate.enabled)
11307                 R_RenderWaterPlanes();
11308
11309         R_RenderScene();
11310         r_waterstate.numwaterplanes = 0;
11311
11312         R_BlendView();
11313         if (r_timereport_active)
11314                 R_TimeReport("blendview");
11315
11316         GL_Scissor(0, 0, vid.width, vid.height);
11317         GL_ScissorTest(false);
11318
11319         r_refdef.view.matrix = originalmatrix;
11320
11321         CHECKGLERROR
11322 }
11323
11324 void R_RenderWaterPlanes(void)
11325 {
11326         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
11327         {
11328                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
11329                 if (r_timereport_active)
11330                         R_TimeReport("waterworld");
11331         }
11332
11333         // don't let sound skip if going slow
11334         if (r_refdef.scene.extraupdate)
11335                 S_ExtraUpdate ();
11336
11337         R_DrawModelsAddWaterPlanes();
11338         if (r_timereport_active)
11339                 R_TimeReport("watermodels");
11340
11341         if (r_waterstate.numwaterplanes)
11342         {
11343                 R_Water_ProcessPlanes();
11344                 if (r_timereport_active)
11345                         R_TimeReport("waterscenes");
11346         }
11347 }
11348
11349 extern void R_DrawLightningBeams (void);
11350 extern void VM_CL_AddPolygonsToMeshQueue (void);
11351 extern void R_DrawPortals (void);
11352 extern cvar_t cl_locs_show;
11353 static void R_DrawLocs(void);
11354 static void R_DrawEntityBBoxes(void);
11355 static void R_DrawModelDecals(void);
11356 extern void R_DrawModelShadows(void);
11357 extern void R_DrawModelShadowMaps(void);
11358 extern cvar_t cl_decals_newsystem;
11359 extern qboolean r_shadow_usingdeferredprepass;
11360 void R_RenderScene(void)
11361 {
11362         qboolean shadowmapping = false;
11363
11364         if (r_timereport_active)
11365                 R_TimeReport("beginscene");
11366
11367         r_refdef.stats.renders++;
11368
11369         R_UpdateFogColor();
11370
11371         // don't let sound skip if going slow
11372         if (r_refdef.scene.extraupdate)
11373                 S_ExtraUpdate ();
11374
11375         R_MeshQueue_BeginScene();
11376
11377         R_SkyStartFrame();
11378
11379         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);
11380
11381         if (r_timereport_active)
11382                 R_TimeReport("skystartframe");
11383
11384         if (cl.csqc_vidvars.drawworld)
11385         {
11386                 // don't let sound skip if going slow
11387                 if (r_refdef.scene.extraupdate)
11388                         S_ExtraUpdate ();
11389
11390                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
11391                 {
11392                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
11393                         if (r_timereport_active)
11394                                 R_TimeReport("worldsky");
11395                 }
11396
11397                 if (R_DrawBrushModelsSky() && r_timereport_active)
11398                         R_TimeReport("bmodelsky");
11399
11400                 if (skyrendermasked && skyrenderlater)
11401                 {
11402                         // we have to force off the water clipping plane while rendering sky
11403                         R_SetupView(false);
11404                         R_Sky();
11405                         R_SetupView(true);
11406                         if (r_timereport_active)
11407                                 R_TimeReport("sky");
11408                 }
11409         }
11410
11411         R_AnimCache_CacheVisibleEntities();
11412         if (r_timereport_active)
11413                 R_TimeReport("animation");
11414
11415         R_Shadow_PrepareLights();
11416         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
11417                 R_Shadow_PrepareModelShadows();
11418         if (r_timereport_active)
11419                 R_TimeReport("preparelights");
11420
11421         if (R_Shadow_ShadowMappingEnabled())
11422                 shadowmapping = true;
11423
11424         if (r_shadow_usingdeferredprepass)
11425                 R_Shadow_DrawPrepass();
11426
11427         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
11428         {
11429                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
11430                 if (r_timereport_active)
11431                         R_TimeReport("worlddepth");
11432         }
11433         if (r_depthfirst.integer >= 2)
11434         {
11435                 R_DrawModelsDepth();
11436                 if (r_timereport_active)
11437                         R_TimeReport("modeldepth");
11438         }
11439
11440         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
11441         {
11442                 R_DrawModelShadowMaps();
11443                 R_ResetViewRendering3D();
11444                 // don't let sound skip if going slow
11445                 if (r_refdef.scene.extraupdate)
11446                         S_ExtraUpdate ();
11447         }
11448
11449         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
11450         {
11451                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
11452                 if (r_timereport_active)
11453                         R_TimeReport("world");
11454         }
11455
11456         // don't let sound skip if going slow
11457         if (r_refdef.scene.extraupdate)
11458                 S_ExtraUpdate ();
11459
11460         R_DrawModels();
11461         if (r_timereport_active)
11462                 R_TimeReport("models");
11463
11464         // don't let sound skip if going slow
11465         if (r_refdef.scene.extraupdate)
11466                 S_ExtraUpdate ();
11467
11468         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
11469         {
11470                 R_DrawModelShadows();
11471                 R_ResetViewRendering3D();
11472                 // don't let sound skip if going slow
11473                 if (r_refdef.scene.extraupdate)
11474                         S_ExtraUpdate ();
11475         }
11476
11477         if (!r_shadow_usingdeferredprepass)
11478         {
11479                 R_Shadow_DrawLights();
11480                 if (r_timereport_active)
11481                         R_TimeReport("rtlights");
11482         }
11483
11484         // don't let sound skip if going slow
11485         if (r_refdef.scene.extraupdate)
11486                 S_ExtraUpdate ();
11487
11488         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
11489         {
11490                 R_DrawModelShadows();
11491                 R_ResetViewRendering3D();
11492                 // don't let sound skip if going slow
11493                 if (r_refdef.scene.extraupdate)
11494                         S_ExtraUpdate ();
11495         }
11496
11497         if (cl.csqc_vidvars.drawworld)
11498         {
11499                 if (cl_decals_newsystem.integer)
11500                 {
11501                         R_DrawModelDecals();
11502                         if (r_timereport_active)
11503                                 R_TimeReport("modeldecals");
11504                 }
11505                 else
11506                 {
11507                         R_DrawDecals();
11508                         if (r_timereport_active)
11509                                 R_TimeReport("decals");
11510                 }
11511
11512                 R_DrawParticles();
11513                 if (r_timereport_active)
11514                         R_TimeReport("particles");
11515
11516                 R_DrawExplosions();
11517                 if (r_timereport_active)
11518                         R_TimeReport("explosions");
11519
11520                 R_DrawLightningBeams();
11521                 if (r_timereport_active)
11522                         R_TimeReport("lightning");
11523         }
11524
11525         VM_CL_AddPolygonsToMeshQueue();
11526
11527         if (r_refdef.view.showdebug)
11528         {
11529                 if (cl_locs_show.integer)
11530                 {
11531                         R_DrawLocs();
11532                         if (r_timereport_active)
11533                                 R_TimeReport("showlocs");
11534                 }
11535
11536                 if (r_drawportals.integer)
11537                 {
11538                         R_DrawPortals();
11539                         if (r_timereport_active)
11540                                 R_TimeReport("portals");
11541                 }
11542
11543                 if (r_showbboxes.value > 0)
11544                 {
11545                         R_DrawEntityBBoxes();
11546                         if (r_timereport_active)
11547                                 R_TimeReport("bboxes");
11548                 }
11549         }
11550
11551         R_MeshQueue_RenderTransparent();
11552         if (r_timereport_active)
11553                 R_TimeReport("drawtrans");
11554
11555         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))
11556         {
11557                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
11558                 if (r_timereport_active)
11559                         R_TimeReport("worlddebug");
11560                 R_DrawModelsDebug();
11561                 if (r_timereport_active)
11562                         R_TimeReport("modeldebug");
11563         }
11564
11565         if (cl.csqc_vidvars.drawworld)
11566         {
11567                 R_Shadow_DrawCoronas();
11568                 if (r_timereport_active)
11569                         R_TimeReport("coronas");
11570         }
11571
11572 #if 0
11573         {
11574                 GL_DepthTest(false);
11575                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11576                 GL_Color(1, 1, 1, 1);
11577                 qglBegin(GL_POLYGON);
11578                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
11579                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
11580                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
11581                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
11582                 qglEnd();
11583                 qglBegin(GL_POLYGON);
11584                 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]);
11585                 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]);
11586                 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]);
11587                 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]);
11588                 qglEnd();
11589                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11590         }
11591 #endif
11592
11593         // don't let sound skip if going slow
11594         if (r_refdef.scene.extraupdate)
11595                 S_ExtraUpdate ();
11596
11597         R_ResetViewRendering2D();
11598 }
11599
11600 static const unsigned short bboxelements[36] =
11601 {
11602         5, 1, 3, 5, 3, 7,
11603         6, 2, 0, 6, 0, 4,
11604         7, 3, 2, 7, 2, 6,
11605         4, 0, 1, 4, 1, 5,
11606         4, 5, 7, 4, 7, 6,
11607         1, 0, 2, 1, 2, 3,
11608 };
11609
11610 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
11611 {
11612         int i;
11613         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
11614
11615         RSurf_ActiveWorldEntity();
11616
11617         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11618         GL_DepthMask(false);
11619         GL_DepthRange(0, 1);
11620         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11621 //      R_Mesh_ResetTextureState();
11622
11623         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
11624         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
11625         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
11626         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
11627         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
11628         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
11629         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
11630         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
11631         R_FillColors(color4f, 8, cr, cg, cb, ca);
11632         if (r_refdef.fogenabled)
11633         {
11634                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
11635                 {
11636                         f1 = RSurf_FogVertex(v);
11637                         f2 = 1 - f1;
11638                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
11639                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
11640                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
11641                 }
11642         }
11643         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
11644         R_Mesh_ResetTextureState();
11645         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11646         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
11647 }
11648
11649 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11650 {
11651         int i;
11652         float color[4];
11653         prvm_edict_t *edict;
11654         prvm_prog_t *prog_save = prog;
11655
11656         // this function draws bounding boxes of server entities
11657         if (!sv.active)
11658                 return;
11659
11660         GL_CullFace(GL_NONE);
11661         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11662
11663         prog = 0;
11664         SV_VM_Begin();
11665         for (i = 0;i < numsurfaces;i++)
11666         {
11667                 edict = PRVM_EDICT_NUM(surfacelist[i]);
11668                 switch ((int)edict->fields.server->solid)
11669                 {
11670                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
11671                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
11672                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
11673                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
11674                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
11675                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
11676                 }
11677                 color[3] *= r_showbboxes.value;
11678                 color[3] = bound(0, color[3], 1);
11679                 GL_DepthTest(!r_showdisabledepthtest.integer);
11680                 GL_CullFace(r_refdef.view.cullface_front);
11681                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
11682         }
11683         SV_VM_End();
11684         prog = prog_save;
11685 }
11686
11687 static void R_DrawEntityBBoxes(void)
11688 {
11689         int i;
11690         prvm_edict_t *edict;
11691         vec3_t center;
11692         prvm_prog_t *prog_save = prog;
11693
11694         // this function draws bounding boxes of server entities
11695         if (!sv.active)
11696                 return;
11697
11698         prog = 0;
11699         SV_VM_Begin();
11700         for (i = 0;i < prog->num_edicts;i++)
11701         {
11702                 edict = PRVM_EDICT_NUM(i);
11703                 if (edict->priv.server->free)
11704                         continue;
11705                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
11706                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
11707                         continue;
11708                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
11709                         continue;
11710                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
11711                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
11712         }
11713         SV_VM_End();
11714         prog = prog_save;
11715 }
11716
11717 static const int nomodelelement3i[24] =
11718 {
11719         5, 2, 0,
11720         5, 1, 2,
11721         5, 0, 3,
11722         5, 3, 1,
11723         0, 2, 4,
11724         2, 1, 4,
11725         3, 0, 4,
11726         1, 3, 4
11727 };
11728
11729 static const unsigned short nomodelelement3s[24] =
11730 {
11731         5, 2, 0,
11732         5, 1, 2,
11733         5, 0, 3,
11734         5, 3, 1,
11735         0, 2, 4,
11736         2, 1, 4,
11737         3, 0, 4,
11738         1, 3, 4
11739 };
11740
11741 static const float nomodelvertex3f[6*3] =
11742 {
11743         -16,   0,   0,
11744          16,   0,   0,
11745           0, -16,   0,
11746           0,  16,   0,
11747           0,   0, -16,
11748           0,   0,  16
11749 };
11750
11751 static const float nomodelcolor4f[6*4] =
11752 {
11753         0.0f, 0.0f, 0.5f, 1.0f,
11754         0.0f, 0.0f, 0.5f, 1.0f,
11755         0.0f, 0.5f, 0.0f, 1.0f,
11756         0.0f, 0.5f, 0.0f, 1.0f,
11757         0.5f, 0.0f, 0.0f, 1.0f,
11758         0.5f, 0.0f, 0.0f, 1.0f
11759 };
11760
11761 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11762 {
11763         int i;
11764         float f1, f2, *c;
11765         float color4f[6*4];
11766
11767         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);
11768
11769         // this is only called once per entity so numsurfaces is always 1, and
11770         // surfacelist is always {0}, so this code does not handle batches
11771
11772         if (rsurface.ent_flags & RENDER_ADDITIVE)
11773         {
11774                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
11775                 GL_DepthMask(false);
11776         }
11777         else if (rsurface.colormod[3] < 1)
11778         {
11779                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11780                 GL_DepthMask(false);
11781         }
11782         else
11783         {
11784                 GL_BlendFunc(GL_ONE, GL_ZERO);
11785                 GL_DepthMask(true);
11786         }
11787         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
11788         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
11789         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
11790         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
11791         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
11792         for (i = 0, c = color4f;i < 6;i++, c += 4)
11793         {
11794                 c[0] *= rsurface.colormod[0];
11795                 c[1] *= rsurface.colormod[1];
11796                 c[2] *= rsurface.colormod[2];
11797                 c[3] *= rsurface.colormod[3];
11798         }
11799         if (r_refdef.fogenabled)
11800         {
11801                 for (i = 0, c = color4f;i < 6;i++, c += 4)
11802                 {
11803                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
11804                         f2 = 1 - f1;
11805                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
11806                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
11807                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
11808                 }
11809         }
11810 //      R_Mesh_ResetTextureState();
11811         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11812         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
11813         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
11814 }
11815
11816 void R_DrawNoModel(entity_render_t *ent)
11817 {
11818         vec3_t org;
11819         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
11820         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
11821                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
11822         else
11823                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
11824 }
11825
11826 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
11827 {
11828         vec3_t right1, right2, diff, normal;
11829
11830         VectorSubtract (org2, org1, normal);
11831
11832         // calculate 'right' vector for start
11833         VectorSubtract (r_refdef.view.origin, org1, diff);
11834         CrossProduct (normal, diff, right1);
11835         VectorNormalize (right1);
11836
11837         // calculate 'right' vector for end
11838         VectorSubtract (r_refdef.view.origin, org2, diff);
11839         CrossProduct (normal, diff, right2);
11840         VectorNormalize (right2);
11841
11842         vert[ 0] = org1[0] + width * right1[0];
11843         vert[ 1] = org1[1] + width * right1[1];
11844         vert[ 2] = org1[2] + width * right1[2];
11845         vert[ 3] = org1[0] - width * right1[0];
11846         vert[ 4] = org1[1] - width * right1[1];
11847         vert[ 5] = org1[2] - width * right1[2];
11848         vert[ 6] = org2[0] - width * right2[0];
11849         vert[ 7] = org2[1] - width * right2[1];
11850         vert[ 8] = org2[2] - width * right2[2];
11851         vert[ 9] = org2[0] + width * right2[0];
11852         vert[10] = org2[1] + width * right2[1];
11853         vert[11] = org2[2] + width * right2[2];
11854 }
11855
11856 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)
11857 {
11858         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
11859         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
11860         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
11861         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
11862         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
11863         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
11864         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
11865         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
11866         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
11867         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
11868         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
11869         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
11870 }
11871
11872 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
11873 {
11874         int i;
11875         float *vertex3f;
11876         float v[3];
11877         VectorSet(v, x, y, z);
11878         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
11879                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
11880                         break;
11881         if (i == mesh->numvertices)
11882         {
11883                 if (mesh->numvertices < mesh->maxvertices)
11884                 {
11885                         VectorCopy(v, vertex3f);
11886                         mesh->numvertices++;
11887                 }
11888                 return mesh->numvertices;
11889         }
11890         else
11891                 return i;
11892 }
11893
11894 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
11895 {
11896         int i;
11897         int *e, element[3];
11898         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
11899         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
11900         e = mesh->element3i + mesh->numtriangles * 3;
11901         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
11902         {
11903                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
11904                 if (mesh->numtriangles < mesh->maxtriangles)
11905                 {
11906                         *e++ = element[0];
11907                         *e++ = element[1];
11908                         *e++ = element[2];
11909                         mesh->numtriangles++;
11910                 }
11911                 element[1] = element[2];
11912         }
11913 }
11914
11915 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
11916 {
11917         int i;
11918         int *e, element[3];
11919         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
11920         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
11921         e = mesh->element3i + mesh->numtriangles * 3;
11922         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
11923         {
11924                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
11925                 if (mesh->numtriangles < mesh->maxtriangles)
11926                 {
11927                         *e++ = element[0];
11928                         *e++ = element[1];
11929                         *e++ = element[2];
11930                         mesh->numtriangles++;
11931                 }
11932                 element[1] = element[2];
11933         }
11934 }
11935
11936 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
11937 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
11938 {
11939         int planenum, planenum2;
11940         int w;
11941         int tempnumpoints;
11942         mplane_t *plane, *plane2;
11943         double maxdist;
11944         double temppoints[2][256*3];
11945         // figure out how large a bounding box we need to properly compute this brush
11946         maxdist = 0;
11947         for (w = 0;w < numplanes;w++)
11948                 maxdist = max(maxdist, fabs(planes[w].dist));
11949         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
11950         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
11951         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
11952         {
11953                 w = 0;
11954                 tempnumpoints = 4;
11955                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
11956                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
11957                 {
11958                         if (planenum2 == planenum)
11959                                 continue;
11960                         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);
11961                         w = !w;
11962                 }
11963                 if (tempnumpoints < 3)
11964                         continue;
11965                 // generate elements forming a triangle fan for this polygon
11966                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
11967         }
11968 }
11969
11970 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)
11971 {
11972         texturelayer_t *layer;
11973         layer = t->currentlayers + t->currentnumlayers++;
11974         layer->type = type;
11975         layer->depthmask = depthmask;
11976         layer->blendfunc1 = blendfunc1;
11977         layer->blendfunc2 = blendfunc2;
11978         layer->texture = texture;
11979         layer->texmatrix = *matrix;
11980         layer->color[0] = r;
11981         layer->color[1] = g;
11982         layer->color[2] = b;
11983         layer->color[3] = a;
11984 }
11985
11986 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
11987 {
11988         if(parms[0] == 0 && parms[1] == 0)
11989                 return false;
11990         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
11991                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
11992                         return false;
11993         return true;
11994 }
11995
11996 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
11997 {
11998         double index, f;
11999         index = parms[2] + r_refdef.scene.time * parms[3];
12000         index -= floor(index);
12001         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
12002         {
12003         default:
12004         case Q3WAVEFUNC_NONE:
12005         case Q3WAVEFUNC_NOISE:
12006         case Q3WAVEFUNC_COUNT:
12007                 f = 0;
12008                 break;
12009         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
12010         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
12011         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
12012         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
12013         case Q3WAVEFUNC_TRIANGLE:
12014                 index *= 4;
12015                 f = index - floor(index);
12016                 if (index < 1)
12017                         f = f;
12018                 else if (index < 2)
12019                         f = 1 - f;
12020                 else if (index < 3)
12021                         f = -f;
12022                 else
12023                         f = -(1 - f);
12024                 break;
12025         }
12026         f = parms[0] + parms[1] * f;
12027         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
12028                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
12029         return (float) f;
12030 }
12031
12032 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
12033 {
12034         int w, h, idx;
12035         float f;
12036         float tcmat[12];
12037         matrix4x4_t matrix, temp;
12038         switch(tcmod->tcmod)
12039         {
12040                 case Q3TCMOD_COUNT:
12041                 case Q3TCMOD_NONE:
12042                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
12043                                 matrix = r_waterscrollmatrix;
12044                         else
12045                                 matrix = identitymatrix;
12046                         break;
12047                 case Q3TCMOD_ENTITYTRANSLATE:
12048                         // this is used in Q3 to allow the gamecode to control texcoord
12049                         // scrolling on the entity, which is not supported in darkplaces yet.
12050                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
12051                         break;
12052                 case Q3TCMOD_ROTATE:
12053                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
12054                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
12055                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
12056                         break;
12057                 case Q3TCMOD_SCALE:
12058                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
12059                         break;
12060                 case Q3TCMOD_SCROLL:
12061                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
12062                         break;
12063                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
12064                         w = (int) tcmod->parms[0];
12065                         h = (int) tcmod->parms[1];
12066                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
12067                         f = f - floor(f);
12068                         idx = (int) floor(f * w * h);
12069                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
12070                         break;
12071                 case Q3TCMOD_STRETCH:
12072                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
12073                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
12074                         break;
12075                 case Q3TCMOD_TRANSFORM:
12076                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
12077                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
12078                         VectorSet(tcmat +  6, 0                   , 0                , 1);
12079                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
12080                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
12081                         break;
12082                 case Q3TCMOD_TURBULENT:
12083                         // this is handled in the RSurf_PrepareVertices function
12084                         matrix = identitymatrix;
12085                         break;
12086         }
12087         temp = *texmatrix;
12088         Matrix4x4_Concat(texmatrix, &matrix, &temp);
12089 }
12090
12091 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
12092 {
12093         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
12094         char name[MAX_QPATH];
12095         skinframe_t *skinframe;
12096         unsigned char pixels[296*194];
12097         strlcpy(cache->name, skinname, sizeof(cache->name));
12098         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
12099         if (developer_loading.integer)
12100                 Con_Printf("loading %s\n", name);
12101         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
12102         if (!skinframe || !skinframe->base)
12103         {
12104                 unsigned char *f;
12105                 fs_offset_t filesize;
12106                 skinframe = NULL;
12107                 f = FS_LoadFile(name, tempmempool, true, &filesize);
12108                 if (f)
12109                 {
12110                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
12111                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
12112                         Mem_Free(f);
12113                 }
12114         }
12115         cache->skinframe = skinframe;
12116 }
12117
12118 texture_t *R_GetCurrentTexture(texture_t *t)
12119 {
12120         int i;
12121         const entity_render_t *ent = rsurface.entity;
12122         dp_model_t *model = ent->model;
12123         q3shaderinfo_layer_tcmod_t *tcmod;
12124
12125         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
12126                 return t->currentframe;
12127         t->update_lastrenderframe = r_textureframe;
12128         t->update_lastrenderentity = (void *)ent;
12129
12130         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
12131                 t->camera_entity = ent->entitynumber;
12132         else
12133                 t->camera_entity = 0;
12134
12135         // switch to an alternate material if this is a q1bsp animated material
12136         {
12137                 texture_t *texture = t;
12138                 int s = rsurface.ent_skinnum;
12139                 if ((unsigned int)s >= (unsigned int)model->numskins)
12140                         s = 0;
12141                 if (model->skinscenes)
12142                 {
12143                         if (model->skinscenes[s].framecount > 1)
12144                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
12145                         else
12146                                 s = model->skinscenes[s].firstframe;
12147                 }
12148                 if (s > 0)
12149                         t = t + s * model->num_surfaces;
12150                 if (t->animated)
12151                 {
12152                         // use an alternate animation if the entity's frame is not 0,
12153                         // and only if the texture has an alternate animation
12154                         if (rsurface.ent_alttextures && t->anim_total[1])
12155                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
12156                         else
12157                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
12158                 }
12159                 texture->currentframe = t;
12160         }
12161
12162         // update currentskinframe to be a qw skin or animation frame
12163         if (rsurface.ent_qwskin >= 0)
12164         {
12165                 i = rsurface.ent_qwskin;
12166                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
12167                 {
12168                         r_qwskincache_size = cl.maxclients;
12169                         if (r_qwskincache)
12170                                 Mem_Free(r_qwskincache);
12171                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
12172                 }
12173                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
12174                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
12175                 t->currentskinframe = r_qwskincache[i].skinframe;
12176                 if (t->currentskinframe == NULL)
12177                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
12178         }
12179         else if (t->numskinframes >= 2)
12180                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
12181         if (t->backgroundnumskinframes >= 2)
12182                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
12183
12184         t->currentmaterialflags = t->basematerialflags;
12185         t->currentalpha = rsurface.colormod[3];
12186         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
12187                 t->currentalpha *= r_wateralpha.value;
12188         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
12189                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
12190         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
12191                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
12192         if (!(rsurface.ent_flags & RENDER_LIGHT))
12193                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
12194         else if (FAKELIGHT_ENABLED)
12195         {
12196                         // no modellight if using fakelight for the map
12197         }
12198         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
12199         {
12200                 // pick a model lighting mode
12201                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
12202                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
12203                 else
12204                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
12205         }
12206         if (rsurface.ent_flags & RENDER_ADDITIVE)
12207                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
12208         else if (t->currentalpha < 1)
12209                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
12210         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
12211                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
12212         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
12213                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
12214         if (t->backgroundnumskinframes)
12215                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
12216         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
12217         {
12218                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
12219                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
12220         }
12221         else
12222                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
12223         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
12224                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
12225
12226         // there is no tcmod
12227         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
12228         {
12229                 t->currenttexmatrix = r_waterscrollmatrix;
12230                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
12231         }
12232         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
12233         {
12234                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
12235                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
12236         }
12237
12238         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
12239                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
12240         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
12241                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
12242
12243         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
12244         if (t->currentskinframe->qpixels)
12245                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
12246         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
12247         if (!t->basetexture)
12248                 t->basetexture = r_texture_notexture;
12249         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
12250         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
12251         t->nmaptexture = t->currentskinframe->nmap;
12252         if (!t->nmaptexture)
12253                 t->nmaptexture = r_texture_blanknormalmap;
12254         t->glosstexture = r_texture_black;
12255         t->glowtexture = t->currentskinframe->glow;
12256         t->fogtexture = t->currentskinframe->fog;
12257         t->reflectmasktexture = t->currentskinframe->reflect;
12258         if (t->backgroundnumskinframes)
12259         {
12260                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
12261                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
12262                 t->backgroundglosstexture = r_texture_black;
12263                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
12264                 if (!t->backgroundnmaptexture)
12265                         t->backgroundnmaptexture = r_texture_blanknormalmap;
12266         }
12267         else
12268         {
12269                 t->backgroundbasetexture = r_texture_white;
12270                 t->backgroundnmaptexture = r_texture_blanknormalmap;
12271                 t->backgroundglosstexture = r_texture_black;
12272                 t->backgroundglowtexture = NULL;
12273         }
12274         t->specularpower = r_shadow_glossexponent.value;
12275         // TODO: store reference values for these in the texture?
12276         t->specularscale = 0;
12277         if (r_shadow_gloss.integer > 0)
12278         {
12279                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
12280                 {
12281                         if (r_shadow_glossintensity.value > 0)
12282                         {
12283                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
12284                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
12285                                 t->specularscale = r_shadow_glossintensity.value;
12286                         }
12287                 }
12288                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
12289                 {
12290                         t->glosstexture = r_texture_white;
12291                         t->backgroundglosstexture = r_texture_white;
12292                         t->specularscale = r_shadow_gloss2intensity.value;
12293                         t->specularpower = r_shadow_gloss2exponent.value;
12294                 }
12295         }
12296         t->specularscale *= t->specularscalemod;
12297         t->specularpower *= t->specularpowermod;
12298
12299         // lightmaps mode looks bad with dlights using actual texturing, so turn
12300         // off the colormap and glossmap, but leave the normalmap on as it still
12301         // accurately represents the shading involved
12302         if (gl_lightmaps.integer)
12303         {
12304                 t->basetexture = r_texture_grey128;
12305                 t->pantstexture = r_texture_black;
12306                 t->shirttexture = r_texture_black;
12307                 t->nmaptexture = r_texture_blanknormalmap;
12308                 t->glosstexture = r_texture_black;
12309                 t->glowtexture = NULL;
12310                 t->fogtexture = NULL;
12311                 t->reflectmasktexture = NULL;
12312                 t->backgroundbasetexture = NULL;
12313                 t->backgroundnmaptexture = r_texture_blanknormalmap;
12314                 t->backgroundglosstexture = r_texture_black;
12315                 t->backgroundglowtexture = NULL;
12316                 t->specularscale = 0;
12317                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
12318         }
12319
12320         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
12321         VectorClear(t->dlightcolor);
12322         t->currentnumlayers = 0;
12323         if (t->currentmaterialflags & MATERIALFLAG_WALL)
12324         {
12325                 int blendfunc1, blendfunc2;
12326                 qboolean depthmask;
12327                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
12328                 {
12329                         blendfunc1 = GL_SRC_ALPHA;
12330                         blendfunc2 = GL_ONE;
12331                 }
12332                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
12333                 {
12334                         blendfunc1 = GL_SRC_ALPHA;
12335                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
12336                 }
12337                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12338                 {
12339                         blendfunc1 = t->customblendfunc[0];
12340                         blendfunc2 = t->customblendfunc[1];
12341                 }
12342                 else
12343                 {
12344                         blendfunc1 = GL_ONE;
12345                         blendfunc2 = GL_ZERO;
12346                 }
12347                 // don't colormod evilblend textures
12348                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
12349                         VectorSet(t->lightmapcolor, 1, 1, 1);
12350                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
12351                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12352                 {
12353                         // fullbright is not affected by r_refdef.lightmapintensity
12354                         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]);
12355                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
12356                                 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]);
12357                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
12358                                 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]);
12359                 }
12360                 else
12361                 {
12362                         vec3_t ambientcolor;
12363                         float colorscale;
12364                         // set the color tint used for lights affecting this surface
12365                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
12366                         colorscale = 2;
12367                         // q3bsp has no lightmap updates, so the lightstylevalue that
12368                         // would normally be baked into the lightmap must be
12369                         // applied to the color
12370                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
12371                         if (model->type == mod_brushq3)
12372                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
12373                         colorscale *= r_refdef.lightmapintensity;
12374                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
12375                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
12376                         // basic lit geometry
12377                         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]);
12378                         // add pants/shirt if needed
12379                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
12380                                 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]);
12381                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
12382                                 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]);
12383                         // now add ambient passes if needed
12384                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
12385                         {
12386                                 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]);
12387                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
12388                                         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]);
12389                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
12390                                         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]);
12391                         }
12392                 }
12393                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
12394                         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]);
12395                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
12396                 {
12397                         // if this is opaque use alpha blend which will darken the earlier
12398                         // passes cheaply.
12399                         //
12400                         // if this is an alpha blended material, all the earlier passes
12401                         // were darkened by fog already, so we only need to add the fog
12402                         // color ontop through the fog mask texture
12403                         //
12404                         // if this is an additive blended material, all the earlier passes
12405                         // were darkened by fog already, and we should not add fog color
12406                         // (because the background was not darkened, there is no fog color
12407                         // that was lost behind it).
12408                         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]);
12409                 }
12410         }
12411
12412         return t->currentframe;
12413 }
12414
12415 rsurfacestate_t rsurface;
12416
12417 void RSurf_ActiveWorldEntity(void)
12418 {
12419         dp_model_t *model = r_refdef.scene.worldmodel;
12420         //if (rsurface.entity == r_refdef.scene.worldentity)
12421         //      return;
12422         rsurface.entity = r_refdef.scene.worldentity;
12423         rsurface.skeleton = NULL;
12424         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
12425         rsurface.ent_skinnum = 0;
12426         rsurface.ent_qwskin = -1;
12427         rsurface.ent_shadertime = 0;
12428         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
12429         rsurface.matrix = identitymatrix;
12430         rsurface.inversematrix = identitymatrix;
12431         rsurface.matrixscale = 1;
12432         rsurface.inversematrixscale = 1;
12433         R_EntityMatrix(&identitymatrix);
12434         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
12435         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
12436         rsurface.fograngerecip = r_refdef.fograngerecip;
12437         rsurface.fogheightfade = r_refdef.fogheightfade;
12438         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
12439         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
12440         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
12441         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
12442         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
12443         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
12444         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
12445         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
12446         rsurface.colormod[3] = 1;
12447         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);
12448         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
12449         rsurface.frameblend[0].lerp = 1;
12450         rsurface.ent_alttextures = false;
12451         rsurface.basepolygonfactor = r_refdef.polygonfactor;
12452         rsurface.basepolygonoffset = r_refdef.polygonoffset;
12453         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
12454         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12455         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
12456         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
12457         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12458         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
12459         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
12460         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12461         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
12462         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
12463         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12464         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
12465         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
12466         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12467         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
12468         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
12469         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12470         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
12471         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
12472         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12473         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
12474         rsurface.modelelement3i = model->surfmesh.data_element3i;
12475         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
12476         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
12477         rsurface.modelelement3s = model->surfmesh.data_element3s;
12478         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
12479         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
12480         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
12481         rsurface.modelnumvertices = model->surfmesh.num_vertices;
12482         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
12483         rsurface.modelsurfaces = model->data_surfaces;
12484         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
12485         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
12486         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
12487         rsurface.modelgeneratedvertex = false;
12488         rsurface.batchgeneratedvertex = false;
12489         rsurface.batchfirstvertex = 0;
12490         rsurface.batchnumvertices = 0;
12491         rsurface.batchfirsttriangle = 0;
12492         rsurface.batchnumtriangles = 0;
12493         rsurface.batchvertex3f  = NULL;
12494         rsurface.batchvertex3f_vertexbuffer = NULL;
12495         rsurface.batchvertex3f_bufferoffset = 0;
12496         rsurface.batchsvector3f = NULL;
12497         rsurface.batchsvector3f_vertexbuffer = NULL;
12498         rsurface.batchsvector3f_bufferoffset = 0;
12499         rsurface.batchtvector3f = NULL;
12500         rsurface.batchtvector3f_vertexbuffer = NULL;
12501         rsurface.batchtvector3f_bufferoffset = 0;
12502         rsurface.batchnormal3f  = NULL;
12503         rsurface.batchnormal3f_vertexbuffer = NULL;
12504         rsurface.batchnormal3f_bufferoffset = 0;
12505         rsurface.batchlightmapcolor4f = NULL;
12506         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
12507         rsurface.batchlightmapcolor4f_bufferoffset = 0;
12508         rsurface.batchtexcoordtexture2f = NULL;
12509         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12510         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12511         rsurface.batchtexcoordlightmap2f = NULL;
12512         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
12513         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
12514         rsurface.batchvertexmesh = NULL;
12515         rsurface.batchvertexmeshbuffer = NULL;
12516         rsurface.batchvertex3fbuffer = NULL;
12517         rsurface.batchelement3i = NULL;
12518         rsurface.batchelement3i_indexbuffer = NULL;
12519         rsurface.batchelement3i_bufferoffset = 0;
12520         rsurface.batchelement3s = NULL;
12521         rsurface.batchelement3s_indexbuffer = NULL;
12522         rsurface.batchelement3s_bufferoffset = 0;
12523         rsurface.passcolor4f = NULL;
12524         rsurface.passcolor4f_vertexbuffer = NULL;
12525         rsurface.passcolor4f_bufferoffset = 0;
12526 }
12527
12528 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
12529 {
12530         dp_model_t *model = ent->model;
12531         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
12532         //      return;
12533         rsurface.entity = (entity_render_t *)ent;
12534         rsurface.skeleton = ent->skeleton;
12535         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
12536         rsurface.ent_skinnum = ent->skinnum;
12537         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;
12538         rsurface.ent_shadertime = ent->shadertime;
12539         rsurface.ent_flags = ent->flags;
12540         rsurface.matrix = ent->matrix;
12541         rsurface.inversematrix = ent->inversematrix;
12542         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
12543         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
12544         R_EntityMatrix(&rsurface.matrix);
12545         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
12546         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
12547         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
12548         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
12549         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
12550         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
12551         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
12552         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
12553         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
12554         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
12555         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
12556         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
12557         rsurface.colormod[3] = ent->alpha;
12558         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
12559         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
12560         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
12561         rsurface.basepolygonfactor = r_refdef.polygonfactor;
12562         rsurface.basepolygonoffset = r_refdef.polygonoffset;
12563         if (ent->model->brush.submodel && !prepass)
12564         {
12565                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
12566                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
12567         }
12568         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
12569         {
12570                 if (ent->animcache_vertex3f)
12571                 {
12572                         rsurface.modelvertex3f = ent->animcache_vertex3f;
12573                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
12574                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
12575                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
12576                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
12577                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
12578                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
12579                 }
12580                 else if (wanttangents)
12581                 {
12582                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
12583                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
12584                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
12585                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
12586                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
12587                         rsurface.modelvertexmesh = NULL;
12588                         rsurface.modelvertexmeshbuffer = NULL;
12589                         rsurface.modelvertex3fbuffer = NULL;
12590                 }
12591                 else if (wantnormals)
12592                 {
12593                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
12594                         rsurface.modelsvector3f = NULL;
12595                         rsurface.modeltvector3f = NULL;
12596                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
12597                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
12598                         rsurface.modelvertexmesh = NULL;
12599                         rsurface.modelvertexmeshbuffer = NULL;
12600                         rsurface.modelvertex3fbuffer = NULL;
12601                 }
12602                 else
12603                 {
12604                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
12605                         rsurface.modelsvector3f = NULL;
12606                         rsurface.modeltvector3f = NULL;
12607                         rsurface.modelnormal3f = NULL;
12608                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
12609                         rsurface.modelvertexmesh = NULL;
12610                         rsurface.modelvertexmeshbuffer = NULL;
12611                         rsurface.modelvertex3fbuffer = NULL;
12612                 }
12613                 rsurface.modelvertex3f_vertexbuffer = 0;
12614                 rsurface.modelvertex3f_bufferoffset = 0;
12615                 rsurface.modelsvector3f_vertexbuffer = 0;
12616                 rsurface.modelsvector3f_bufferoffset = 0;
12617                 rsurface.modeltvector3f_vertexbuffer = 0;
12618                 rsurface.modeltvector3f_bufferoffset = 0;
12619                 rsurface.modelnormal3f_vertexbuffer = 0;
12620                 rsurface.modelnormal3f_bufferoffset = 0;
12621                 rsurface.modelgeneratedvertex = true;
12622         }
12623         else
12624         {
12625                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
12626                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12627                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
12628                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
12629                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12630                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
12631                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
12632                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12633                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
12634                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
12635                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12636                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
12637                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
12638                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
12639                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
12640                 rsurface.modelgeneratedvertex = false;
12641         }
12642         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
12643         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12644         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
12645         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
12646         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12647         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
12648         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
12649         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
12650         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
12651         rsurface.modelelement3i = model->surfmesh.data_element3i;
12652         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
12653         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
12654         rsurface.modelelement3s = model->surfmesh.data_element3s;
12655         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
12656         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
12657         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
12658         rsurface.modelnumvertices = model->surfmesh.num_vertices;
12659         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
12660         rsurface.modelsurfaces = model->data_surfaces;
12661         rsurface.batchgeneratedvertex = false;
12662         rsurface.batchfirstvertex = 0;
12663         rsurface.batchnumvertices = 0;
12664         rsurface.batchfirsttriangle = 0;
12665         rsurface.batchnumtriangles = 0;
12666         rsurface.batchvertex3f  = NULL;
12667         rsurface.batchvertex3f_vertexbuffer = NULL;
12668         rsurface.batchvertex3f_bufferoffset = 0;
12669         rsurface.batchsvector3f = NULL;
12670         rsurface.batchsvector3f_vertexbuffer = NULL;
12671         rsurface.batchsvector3f_bufferoffset = 0;
12672         rsurface.batchtvector3f = NULL;
12673         rsurface.batchtvector3f_vertexbuffer = NULL;
12674         rsurface.batchtvector3f_bufferoffset = 0;
12675         rsurface.batchnormal3f  = NULL;
12676         rsurface.batchnormal3f_vertexbuffer = NULL;
12677         rsurface.batchnormal3f_bufferoffset = 0;
12678         rsurface.batchlightmapcolor4f = NULL;
12679         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
12680         rsurface.batchlightmapcolor4f_bufferoffset = 0;
12681         rsurface.batchtexcoordtexture2f = NULL;
12682         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12683         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12684         rsurface.batchtexcoordlightmap2f = NULL;
12685         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
12686         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
12687         rsurface.batchvertexmesh = NULL;
12688         rsurface.batchvertexmeshbuffer = NULL;
12689         rsurface.batchvertex3fbuffer = NULL;
12690         rsurface.batchelement3i = NULL;
12691         rsurface.batchelement3i_indexbuffer = NULL;
12692         rsurface.batchelement3i_bufferoffset = 0;
12693         rsurface.batchelement3s = NULL;
12694         rsurface.batchelement3s_indexbuffer = NULL;
12695         rsurface.batchelement3s_bufferoffset = 0;
12696         rsurface.passcolor4f = NULL;
12697         rsurface.passcolor4f_vertexbuffer = NULL;
12698         rsurface.passcolor4f_bufferoffset = 0;
12699 }
12700
12701 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)
12702 {
12703         rsurface.entity = r_refdef.scene.worldentity;
12704         rsurface.skeleton = NULL;
12705         rsurface.ent_skinnum = 0;
12706         rsurface.ent_qwskin = -1;
12707         rsurface.ent_shadertime = shadertime;
12708         rsurface.ent_flags = entflags;
12709         rsurface.modelnumvertices = numvertices;
12710         rsurface.modelnumtriangles = numtriangles;
12711         rsurface.matrix = *matrix;
12712         rsurface.inversematrix = *inversematrix;
12713         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
12714         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
12715         R_EntityMatrix(&rsurface.matrix);
12716         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
12717         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
12718         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
12719         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
12720         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
12721         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
12722         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
12723         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
12724         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
12725         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
12726         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
12727         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
12728         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);
12729         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
12730         rsurface.frameblend[0].lerp = 1;
12731         rsurface.ent_alttextures = false;
12732         rsurface.basepolygonfactor = r_refdef.polygonfactor;
12733         rsurface.basepolygonoffset = r_refdef.polygonoffset;
12734         if (wanttangents)
12735         {
12736                 rsurface.modelvertex3f = (float *)vertex3f;
12737                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
12738                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
12739                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
12740         }
12741         else if (wantnormals)
12742         {
12743                 rsurface.modelvertex3f = (float *)vertex3f;
12744                 rsurface.modelsvector3f = NULL;
12745                 rsurface.modeltvector3f = NULL;
12746                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
12747         }
12748         else
12749         {
12750                 rsurface.modelvertex3f = (float *)vertex3f;
12751                 rsurface.modelsvector3f = NULL;
12752                 rsurface.modeltvector3f = NULL;
12753                 rsurface.modelnormal3f = NULL;
12754         }
12755         rsurface.modelvertexmesh = NULL;
12756         rsurface.modelvertexmeshbuffer = NULL;
12757         rsurface.modelvertex3fbuffer = NULL;
12758         rsurface.modelvertex3f_vertexbuffer = 0;
12759         rsurface.modelvertex3f_bufferoffset = 0;
12760         rsurface.modelsvector3f_vertexbuffer = 0;
12761         rsurface.modelsvector3f_bufferoffset = 0;
12762         rsurface.modeltvector3f_vertexbuffer = 0;
12763         rsurface.modeltvector3f_bufferoffset = 0;
12764         rsurface.modelnormal3f_vertexbuffer = 0;
12765         rsurface.modelnormal3f_bufferoffset = 0;
12766         rsurface.modelgeneratedvertex = true;
12767         rsurface.modellightmapcolor4f  = (float *)color4f;
12768         rsurface.modellightmapcolor4f_vertexbuffer = 0;
12769         rsurface.modellightmapcolor4f_bufferoffset = 0;
12770         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
12771         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
12772         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
12773         rsurface.modeltexcoordlightmap2f  = NULL;
12774         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
12775         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
12776         rsurface.modelelement3i = (int *)element3i;
12777         rsurface.modelelement3i_indexbuffer = NULL;
12778         rsurface.modelelement3i_bufferoffset = 0;
12779         rsurface.modelelement3s = (unsigned short *)element3s;
12780         rsurface.modelelement3s_indexbuffer = NULL;
12781         rsurface.modelelement3s_bufferoffset = 0;
12782         rsurface.modellightmapoffsets = NULL;
12783         rsurface.modelsurfaces = NULL;
12784         rsurface.batchgeneratedvertex = false;
12785         rsurface.batchfirstvertex = 0;
12786         rsurface.batchnumvertices = 0;
12787         rsurface.batchfirsttriangle = 0;
12788         rsurface.batchnumtriangles = 0;
12789         rsurface.batchvertex3f  = NULL;
12790         rsurface.batchvertex3f_vertexbuffer = NULL;
12791         rsurface.batchvertex3f_bufferoffset = 0;
12792         rsurface.batchsvector3f = NULL;
12793         rsurface.batchsvector3f_vertexbuffer = NULL;
12794         rsurface.batchsvector3f_bufferoffset = 0;
12795         rsurface.batchtvector3f = NULL;
12796         rsurface.batchtvector3f_vertexbuffer = NULL;
12797         rsurface.batchtvector3f_bufferoffset = 0;
12798         rsurface.batchnormal3f  = NULL;
12799         rsurface.batchnormal3f_vertexbuffer = NULL;
12800         rsurface.batchnormal3f_bufferoffset = 0;
12801         rsurface.batchlightmapcolor4f = NULL;
12802         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
12803         rsurface.batchlightmapcolor4f_bufferoffset = 0;
12804         rsurface.batchtexcoordtexture2f = NULL;
12805         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12806         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12807         rsurface.batchtexcoordlightmap2f = NULL;
12808         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
12809         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
12810         rsurface.batchvertexmesh = NULL;
12811         rsurface.batchvertexmeshbuffer = NULL;
12812         rsurface.batchvertex3fbuffer = NULL;
12813         rsurface.batchelement3i = NULL;
12814         rsurface.batchelement3i_indexbuffer = NULL;
12815         rsurface.batchelement3i_bufferoffset = 0;
12816         rsurface.batchelement3s = NULL;
12817         rsurface.batchelement3s_indexbuffer = NULL;
12818         rsurface.batchelement3s_bufferoffset = 0;
12819         rsurface.passcolor4f = NULL;
12820         rsurface.passcolor4f_vertexbuffer = NULL;
12821         rsurface.passcolor4f_bufferoffset = 0;
12822
12823         if (rsurface.modelnumvertices && rsurface.modelelement3i)
12824         {
12825                 if ((wantnormals || wanttangents) && !normal3f)
12826                 {
12827                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
12828                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
12829                 }
12830                 if (wanttangents && !svector3f)
12831                 {
12832                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
12833                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
12834                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
12835                 }
12836         }
12837 }
12838
12839 float RSurf_FogPoint(const float *v)
12840 {
12841         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
12842         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
12843         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
12844         float FogHeightFade = r_refdef.fogheightfade;
12845         float fogfrac;
12846         unsigned int fogmasktableindex;
12847         if (r_refdef.fogplaneviewabove)
12848                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
12849         else
12850                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
12851         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
12852         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
12853 }
12854
12855 float RSurf_FogVertex(const float *v)
12856 {
12857         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
12858         float FogPlaneViewDist = rsurface.fogplaneviewdist;
12859         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
12860         float FogHeightFade = rsurface.fogheightfade;
12861         float fogfrac;
12862         unsigned int fogmasktableindex;
12863         if (r_refdef.fogplaneviewabove)
12864                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
12865         else
12866                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
12867         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
12868         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
12869 }
12870
12871 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
12872 {
12873         int i;
12874         for (i = 0;i < numelements;i++)
12875                 outelement3i[i] = inelement3i[i] + adjust;
12876 }
12877
12878 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
12879 extern cvar_t gl_vbo;
12880 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
12881 {
12882         int deformindex;
12883         int firsttriangle;
12884         int numtriangles;
12885         int firstvertex;
12886         int endvertex;
12887         int numvertices;
12888         int surfacefirsttriangle;
12889         int surfacenumtriangles;
12890         int surfacefirstvertex;
12891         int surfaceendvertex;
12892         int surfacenumvertices;
12893         int batchnumvertices;
12894         int batchnumtriangles;
12895         int needsupdate;
12896         int i, j;
12897         qboolean gaps;
12898         qboolean dynamicvertex;
12899         float amplitude;
12900         float animpos;
12901         float scale;
12902         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
12903         float waveparms[4];
12904         q3shaderinfo_deform_t *deform;
12905         const msurface_t *surface, *firstsurface;
12906         r_vertexmesh_t *vertexmesh;
12907         if (!texturenumsurfaces)
12908                 return;
12909         // find vertex range of this surface batch
12910         gaps = false;
12911         firstsurface = texturesurfacelist[0];
12912         firsttriangle = firstsurface->num_firsttriangle;
12913         batchnumvertices = 0;
12914         batchnumtriangles = 0;
12915         firstvertex = endvertex = firstsurface->num_firstvertex;
12916         for (i = 0;i < texturenumsurfaces;i++)
12917         {
12918                 surface = texturesurfacelist[i];
12919                 if (surface != firstsurface + i)
12920                         gaps = true;
12921                 surfacefirstvertex = surface->num_firstvertex;
12922                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
12923                 surfacenumvertices = surface->num_vertices;
12924                 surfacenumtriangles = surface->num_triangles;
12925                 if (firstvertex > surfacefirstvertex)
12926                         firstvertex = surfacefirstvertex;
12927                 if (endvertex < surfaceendvertex)
12928                         endvertex = surfaceendvertex;
12929                 batchnumvertices += surfacenumvertices;
12930                 batchnumtriangles += surfacenumtriangles;
12931         }
12932
12933         // we now know the vertex range used, and if there are any gaps in it
12934         rsurface.batchfirstvertex = firstvertex;
12935         rsurface.batchnumvertices = endvertex - firstvertex;
12936         rsurface.batchfirsttriangle = firsttriangle;
12937         rsurface.batchnumtriangles = batchnumtriangles;
12938
12939         // this variable holds flags for which properties have been updated that
12940         // may require regenerating vertexmesh array...
12941         needsupdate = 0;
12942
12943         // check if any dynamic vertex processing must occur
12944         dynamicvertex = false;
12945
12946         // if there is a chance of animated vertex colors, it's a dynamic batch
12947         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
12948         {
12949                 dynamicvertex = true;
12950                 batchneed |= BATCHNEED_NOGAPS;
12951                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
12952         }
12953
12954         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
12955         {
12956                 switch (deform->deform)
12957                 {
12958                 default:
12959                 case Q3DEFORM_PROJECTIONSHADOW:
12960                 case Q3DEFORM_TEXT0:
12961                 case Q3DEFORM_TEXT1:
12962                 case Q3DEFORM_TEXT2:
12963                 case Q3DEFORM_TEXT3:
12964                 case Q3DEFORM_TEXT4:
12965                 case Q3DEFORM_TEXT5:
12966                 case Q3DEFORM_TEXT6:
12967                 case Q3DEFORM_TEXT7:
12968                 case Q3DEFORM_NONE:
12969                         break;
12970                 case Q3DEFORM_AUTOSPRITE:
12971                         dynamicvertex = true;
12972                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
12973                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
12974                         break;
12975                 case Q3DEFORM_AUTOSPRITE2:
12976                         dynamicvertex = true;
12977                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
12978                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
12979                         break;
12980                 case Q3DEFORM_NORMAL:
12981                         dynamicvertex = true;
12982                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
12983                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
12984                         break;
12985                 case Q3DEFORM_WAVE:
12986                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12987                                 break; // if wavefunc is a nop, ignore this transform
12988                         dynamicvertex = true;
12989                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
12990                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
12991                         break;
12992                 case Q3DEFORM_BULGE:
12993                         dynamicvertex = true;
12994                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
12995                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
12996                         break;
12997                 case Q3DEFORM_MOVE:
12998                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12999                                 break; // if wavefunc is a nop, ignore this transform
13000                         dynamicvertex = true;
13001                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
13002                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
13003                         break;
13004                 }
13005         }
13006         switch(rsurface.texture->tcgen.tcgen)
13007         {
13008         default:
13009         case Q3TCGEN_TEXTURE:
13010                 break;
13011         case Q3TCGEN_LIGHTMAP:
13012                 dynamicvertex = true;
13013                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
13014                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
13015                 break;
13016         case Q3TCGEN_VECTOR:
13017                 dynamicvertex = true;
13018                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
13019                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
13020                 break;
13021         case Q3TCGEN_ENVIRONMENT:
13022                 dynamicvertex = true;
13023                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
13024                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
13025                 break;
13026         }
13027         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
13028         {
13029                 dynamicvertex = true;
13030                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
13031                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
13032         }
13033
13034         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
13035         {
13036                 dynamicvertex = true;
13037                 batchneed |= BATCHNEED_NOGAPS;
13038                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
13039         }
13040
13041         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
13042         {
13043                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
13044                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
13045                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
13046                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
13047                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
13048                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
13049                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
13050         }
13051
13052         // when the model data has no vertex buffer (dynamic mesh), we need to
13053         // eliminate gaps
13054         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
13055                 batchneed |= BATCHNEED_NOGAPS;
13056
13057         // if needsupdate, we have to do a dynamic vertex batch for sure
13058         if (needsupdate & batchneed)
13059                 dynamicvertex = true;
13060
13061         // see if we need to build vertexmesh from arrays
13062         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
13063                 dynamicvertex = true;
13064
13065         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
13066         // also some drivers strongly dislike firstvertex
13067         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
13068                 dynamicvertex = true;
13069
13070         rsurface.batchvertex3f = rsurface.modelvertex3f;
13071         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
13072         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
13073         rsurface.batchsvector3f = rsurface.modelsvector3f;
13074         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
13075         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
13076         rsurface.batchtvector3f = rsurface.modeltvector3f;
13077         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
13078         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
13079         rsurface.batchnormal3f = rsurface.modelnormal3f;
13080         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
13081         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
13082         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
13083         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
13084         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
13085         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
13086         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
13087         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
13088         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
13089         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
13090         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
13091         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
13092         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
13093         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
13094         rsurface.batchelement3i = rsurface.modelelement3i;
13095         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
13096         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
13097         rsurface.batchelement3s = rsurface.modelelement3s;
13098         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
13099         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
13100
13101         // if any dynamic vertex processing has to occur in software, we copy the
13102         // entire surface list together before processing to rebase the vertices
13103         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
13104         //
13105         // if any gaps exist and we do not have a static vertex buffer, we have to
13106         // copy the surface list together to avoid wasting upload bandwidth on the
13107         // vertices in the gaps.
13108         //
13109         // if gaps exist and we have a static vertex buffer, we still have to
13110         // combine the index buffer ranges into one dynamic index buffer.
13111         //
13112         // in all cases we end up with data that can be drawn in one call.
13113
13114         if (!dynamicvertex)
13115         {
13116                 // static vertex data, just set pointers...
13117                 rsurface.batchgeneratedvertex = false;
13118                 // if there are gaps, we want to build a combined index buffer,
13119                 // otherwise use the original static buffer with an appropriate offset
13120                 if (gaps)
13121                 {
13122                         // build a new triangle elements array for this batch
13123                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
13124                         rsurface.batchfirsttriangle = 0;
13125                         numtriangles = 0;
13126                         for (i = 0;i < texturenumsurfaces;i++)
13127                         {
13128                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
13129                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
13130                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
13131                                 numtriangles += surfacenumtriangles;
13132                         }
13133                         rsurface.batchelement3i_indexbuffer = NULL;
13134                         rsurface.batchelement3i_bufferoffset = 0;
13135                         rsurface.batchelement3s = NULL;
13136                         rsurface.batchelement3s_indexbuffer = NULL;
13137                         rsurface.batchelement3s_bufferoffset = 0;
13138                         if (endvertex <= 65536)
13139                         {
13140                                 // make a 16bit (unsigned short) index array if possible
13141                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
13142                                 for (i = 0;i < numtriangles*3;i++)
13143                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
13144                         }
13145                 }
13146                 return;
13147         }
13148
13149         // something needs software processing, do it for real...
13150         // we only directly handle separate array data in this case and then
13151         // generate interleaved data if needed...
13152         rsurface.batchgeneratedvertex = true;
13153
13154         // now copy the vertex data into a combined array and make an index array
13155         // (this is what Quake3 does all the time)
13156         //if (gaps || rsurface.batchfirstvertex)
13157         {
13158                 rsurface.batchvertex3fbuffer = NULL;
13159                 rsurface.batchvertexmesh = NULL;
13160                 rsurface.batchvertexmeshbuffer = NULL;
13161                 rsurface.batchvertex3f = NULL;
13162                 rsurface.batchvertex3f_vertexbuffer = NULL;
13163                 rsurface.batchvertex3f_bufferoffset = 0;
13164                 rsurface.batchsvector3f = NULL;
13165                 rsurface.batchsvector3f_vertexbuffer = NULL;
13166                 rsurface.batchsvector3f_bufferoffset = 0;
13167                 rsurface.batchtvector3f = NULL;
13168                 rsurface.batchtvector3f_vertexbuffer = NULL;
13169                 rsurface.batchtvector3f_bufferoffset = 0;
13170                 rsurface.batchnormal3f = NULL;
13171                 rsurface.batchnormal3f_vertexbuffer = NULL;
13172                 rsurface.batchnormal3f_bufferoffset = 0;
13173                 rsurface.batchlightmapcolor4f = NULL;
13174                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
13175                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
13176                 rsurface.batchtexcoordtexture2f = NULL;
13177                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
13178                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
13179                 rsurface.batchtexcoordlightmap2f = NULL;
13180                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
13181                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
13182                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
13183                 rsurface.batchelement3i_indexbuffer = NULL;
13184                 rsurface.batchelement3i_bufferoffset = 0;
13185                 rsurface.batchelement3s = NULL;
13186                 rsurface.batchelement3s_indexbuffer = NULL;
13187                 rsurface.batchelement3s_bufferoffset = 0;
13188                 // we'll only be setting up certain arrays as needed
13189                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
13190                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
13191                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
13192                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13193                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
13194                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13195                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
13196                 {
13197                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13198                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13199                 }
13200                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
13201                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
13202                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
13203                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
13204                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
13205                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
13206                 numvertices = 0;
13207                 numtriangles = 0;
13208                 for (i = 0;i < texturenumsurfaces;i++)
13209                 {
13210                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
13211                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
13212                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
13213                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
13214                         // copy only the data requested
13215                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
13216                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
13217                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
13218                         {
13219                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
13220                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
13221                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
13222                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
13223                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
13224                                 {
13225                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
13226                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
13227                                 }
13228                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
13229                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
13230                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
13231                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
13232                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
13233                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
13234                         }
13235                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
13236                         numvertices += surfacenumvertices;
13237                         numtriangles += surfacenumtriangles;
13238                 }
13239
13240                 // generate a 16bit index array as well if possible
13241                 // (in general, dynamic batches fit)
13242                 if (numvertices <= 65536)
13243                 {
13244                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
13245                         for (i = 0;i < numtriangles*3;i++)
13246                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
13247                 }
13248
13249                 // since we've copied everything, the batch now starts at 0
13250                 rsurface.batchfirstvertex = 0;
13251                 rsurface.batchnumvertices = batchnumvertices;
13252                 rsurface.batchfirsttriangle = 0;
13253                 rsurface.batchnumtriangles = batchnumtriangles;
13254         }
13255
13256         // q1bsp surfaces rendered in vertex color mode have to have colors
13257         // calculated based on lightstyles
13258         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
13259         {
13260                 // generate color arrays for the surfaces in this list
13261                 int c[4];
13262                 int scale;
13263                 int size3;
13264                 const int *offsets;
13265                 const unsigned char *lm;
13266                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
13267                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
13268                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
13269                 numvertices = 0;
13270                 for (i = 0;i < texturenumsurfaces;i++)
13271                 {
13272                         surface = texturesurfacelist[i];
13273                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
13274                         surfacenumvertices = surface->num_vertices;
13275                         if (surface->lightmapinfo->samples)
13276                         {
13277                                 for (j = 0;j < surfacenumvertices;j++)
13278                                 {
13279                                         lm = surface->lightmapinfo->samples + offsets[j];
13280                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
13281                                         VectorScale(lm, scale, c);
13282                                         if (surface->lightmapinfo->styles[1] != 255)
13283                                         {
13284                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
13285                                                 lm += size3;
13286                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
13287                                                 VectorMA(c, scale, lm, c);
13288                                                 if (surface->lightmapinfo->styles[2] != 255)
13289                                                 {
13290                                                         lm += size3;
13291                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
13292                                                         VectorMA(c, scale, lm, c);
13293                                                         if (surface->lightmapinfo->styles[3] != 255)
13294                                                         {
13295                                                                 lm += size3;
13296                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
13297                                                                 VectorMA(c, scale, lm, c);
13298                                                         }
13299                                                 }
13300                                         }
13301                                         c[0] >>= 7;
13302                                         c[1] >>= 7;
13303                                         c[2] >>= 7;
13304                                         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);
13305                                         numvertices++;
13306                                 }
13307                         }
13308                         else
13309                         {
13310                                 for (j = 0;j < surfacenumvertices;j++)
13311                                 {
13312                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
13313                                         numvertices++;
13314                                 }
13315                         }
13316                 }
13317         }
13318
13319         // if vertices are deformed (sprite flares and things in maps, possibly
13320         // water waves, bulges and other deformations), modify the copied vertices
13321         // in place
13322         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
13323         {
13324                 switch (deform->deform)
13325                 {
13326                 default:
13327                 case Q3DEFORM_PROJECTIONSHADOW:
13328                 case Q3DEFORM_TEXT0:
13329                 case Q3DEFORM_TEXT1:
13330                 case Q3DEFORM_TEXT2:
13331                 case Q3DEFORM_TEXT3:
13332                 case Q3DEFORM_TEXT4:
13333                 case Q3DEFORM_TEXT5:
13334                 case Q3DEFORM_TEXT6:
13335                 case Q3DEFORM_TEXT7:
13336                 case Q3DEFORM_NONE:
13337                         break;
13338                 case Q3DEFORM_AUTOSPRITE:
13339                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
13340                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
13341                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
13342                         VectorNormalize(newforward);
13343                         VectorNormalize(newright);
13344                         VectorNormalize(newup);
13345 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
13346 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
13347 //                      rsurface.batchvertex3f_bufferoffset = 0;
13348 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
13349 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
13350 //                      rsurface.batchsvector3f_bufferoffset = 0;
13351 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
13352 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
13353 //                      rsurface.batchtvector3f_bufferoffset = 0;
13354 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
13355 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
13356 //                      rsurface.batchnormal3f_bufferoffset = 0;
13357                         // a single autosprite surface can contain multiple sprites...
13358                         for (j = 0;j < batchnumvertices - 3;j += 4)
13359                         {
13360                                 VectorClear(center);
13361                                 for (i = 0;i < 4;i++)
13362                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
13363                                 VectorScale(center, 0.25f, center);
13364                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
13365                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
13366                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
13367                                 for (i = 0;i < 4;i++)
13368                                 {
13369                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
13370                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
13371                                 }
13372                         }
13373                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
13374                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
13375                         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);
13376                         break;
13377                 case Q3DEFORM_AUTOSPRITE2:
13378                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
13379                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
13380                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
13381                         VectorNormalize(newforward);
13382                         VectorNormalize(newright);
13383                         VectorNormalize(newup);
13384 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
13385 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
13386 //                      rsurface.batchvertex3f_bufferoffset = 0;
13387                         {
13388                                 const float *v1, *v2;
13389                                 vec3_t start, end;
13390                                 float f, l;
13391                                 struct
13392                                 {
13393                                         float length2;
13394                                         const float *v1;
13395                                         const float *v2;
13396                                 }
13397                                 shortest[2];
13398                                 memset(shortest, 0, sizeof(shortest));
13399                                 // a single autosprite surface can contain multiple sprites...
13400                                 for (j = 0;j < batchnumvertices - 3;j += 4)
13401                                 {
13402                                         VectorClear(center);
13403                                         for (i = 0;i < 4;i++)
13404                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
13405                                         VectorScale(center, 0.25f, center);
13406                                         // find the two shortest edges, then use them to define the
13407                                         // axis vectors for rotating around the central axis
13408                                         for (i = 0;i < 6;i++)
13409                                         {
13410                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
13411                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
13412                                                 l = VectorDistance2(v1, v2);
13413                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
13414                                                 if (v1[2] != v2[2])
13415                                                         l += (1.0f / 1024.0f);
13416                                                 if (shortest[0].length2 > l || i == 0)
13417                                                 {
13418                                                         shortest[1] = shortest[0];
13419                                                         shortest[0].length2 = l;
13420                                                         shortest[0].v1 = v1;
13421                                                         shortest[0].v2 = v2;
13422                                                 }
13423                                                 else if (shortest[1].length2 > l || i == 1)
13424                                                 {
13425                                                         shortest[1].length2 = l;
13426                                                         shortest[1].v1 = v1;
13427                                                         shortest[1].v2 = v2;
13428                                                 }
13429                                         }
13430                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
13431                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
13432                                         // this calculates the right vector from the shortest edge
13433                                         // and the up vector from the edge midpoints
13434                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
13435                                         VectorNormalize(right);
13436                                         VectorSubtract(end, start, up);
13437                                         VectorNormalize(up);
13438                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
13439                                         VectorSubtract(rsurface.localvieworigin, center, forward);
13440                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
13441                                         VectorNegate(forward, forward);
13442                                         VectorReflect(forward, 0, up, forward);
13443                                         VectorNormalize(forward);
13444                                         CrossProduct(up, forward, newright);
13445                                         VectorNormalize(newright);
13446                                         // rotate the quad around the up axis vector, this is made
13447                                         // especially easy by the fact we know the quad is flat,
13448                                         // so we only have to subtract the center position and
13449                                         // measure distance along the right vector, and then
13450                                         // multiply that by the newright vector and add back the
13451                                         // center position
13452                                         // we also need to subtract the old position to undo the
13453                                         // displacement from the center, which we do with a
13454                                         // DotProduct, the subtraction/addition of center is also
13455                                         // optimized into DotProducts here
13456                                         l = DotProduct(right, center);
13457                                         for (i = 0;i < 4;i++)
13458                                         {
13459                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
13460                                                 f = DotProduct(right, v1) - l;
13461                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
13462                                         }
13463                                 }
13464                         }
13465                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
13466                         {
13467 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13468 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
13469 //                              rsurface.batchnormal3f_bufferoffset = 0;
13470                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
13471                         }
13472                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
13473                         {
13474 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13475 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
13476 //                              rsurface.batchsvector3f_bufferoffset = 0;
13477 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13478 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
13479 //                              rsurface.batchtvector3f_bufferoffset = 0;
13480                                 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);
13481                         }
13482                         break;
13483                 case Q3DEFORM_NORMAL:
13484                         // deform the normals to make reflections wavey
13485                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
13486                         rsurface.batchnormal3f_vertexbuffer = NULL;
13487                         rsurface.batchnormal3f_bufferoffset = 0;
13488                         for (j = 0;j < batchnumvertices;j++)
13489                         {
13490                                 float vertex[3];
13491                                 float *normal = rsurface.batchnormal3f + 3*j;
13492                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
13493                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
13494                                 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]);
13495                                 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]);
13496                                 VectorNormalize(normal);
13497                         }
13498                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
13499                         {
13500 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13501 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
13502 //                              rsurface.batchsvector3f_bufferoffset = 0;
13503 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13504 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
13505 //                              rsurface.batchtvector3f_bufferoffset = 0;
13506                                 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);
13507                         }
13508                         break;
13509                 case Q3DEFORM_WAVE:
13510                         // deform vertex array to make wavey water and flags and such
13511                         waveparms[0] = deform->waveparms[0];
13512                         waveparms[1] = deform->waveparms[1];
13513                         waveparms[2] = deform->waveparms[2];
13514                         waveparms[3] = deform->waveparms[3];
13515                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
13516                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
13517                         // this is how a divisor of vertex influence on deformation
13518                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
13519                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
13520 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
13521 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
13522 //                      rsurface.batchvertex3f_bufferoffset = 0;
13523 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
13524 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
13525 //                      rsurface.batchnormal3f_bufferoffset = 0;
13526                         for (j = 0;j < batchnumvertices;j++)
13527                         {
13528                                 // if the wavefunc depends on time, evaluate it per-vertex
13529                                 if (waveparms[3])
13530                                 {
13531                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
13532                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
13533                                 }
13534                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
13535                         }
13536                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
13537                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
13538                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
13539                         {
13540 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13541 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
13542 //                              rsurface.batchsvector3f_bufferoffset = 0;
13543 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13544 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
13545 //                              rsurface.batchtvector3f_bufferoffset = 0;
13546                                 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);
13547                         }
13548                         break;
13549                 case Q3DEFORM_BULGE:
13550                         // deform vertex array to make the surface have moving bulges
13551 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
13552 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
13553 //                      rsurface.batchvertex3f_bufferoffset = 0;
13554 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
13555 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
13556 //                      rsurface.batchnormal3f_bufferoffset = 0;
13557                         for (j = 0;j < batchnumvertices;j++)
13558                         {
13559                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
13560                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
13561                         }
13562                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
13563                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
13564                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
13565                         {
13566 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13567 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
13568 //                              rsurface.batchsvector3f_bufferoffset = 0;
13569 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
13570 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
13571 //                              rsurface.batchtvector3f_bufferoffset = 0;
13572                                 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);
13573                         }
13574                         break;
13575                 case Q3DEFORM_MOVE:
13576                         // deform vertex array
13577                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
13578                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
13579                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
13580                         VectorScale(deform->parms, scale, waveparms);
13581 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
13582 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
13583 //                      rsurface.batchvertex3f_bufferoffset = 0;
13584                         for (j = 0;j < batchnumvertices;j++)
13585                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
13586                         break;
13587                 }
13588         }
13589
13590         // generate texcoords based on the chosen texcoord source
13591         switch(rsurface.texture->tcgen.tcgen)
13592         {
13593         default:
13594         case Q3TCGEN_TEXTURE:
13595                 break;
13596         case Q3TCGEN_LIGHTMAP:
13597 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
13598 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
13599 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
13600                 if (rsurface.batchtexcoordlightmap2f)
13601                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
13602                 break;
13603         case Q3TCGEN_VECTOR:
13604 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
13605 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
13606 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
13607                 for (j = 0;j < batchnumvertices;j++)
13608                 {
13609                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
13610                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
13611                 }
13612                 break;
13613         case Q3TCGEN_ENVIRONMENT:
13614                 // make environment reflections using a spheremap
13615                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
13616                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
13617                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
13618                 for (j = 0;j < batchnumvertices;j++)
13619                 {
13620                         // identical to Q3A's method, but executed in worldspace so
13621                         // carried models can be shiny too
13622
13623                         float viewer[3], d, reflected[3], worldreflected[3];
13624
13625                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
13626                         // VectorNormalize(viewer);
13627
13628                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
13629
13630                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
13631                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
13632                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
13633                         // note: this is proportinal to viewer, so we can normalize later
13634
13635                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
13636                         VectorNormalize(worldreflected);
13637
13638                         // note: this sphere map only uses world x and z!
13639                         // so positive and negative y will LOOK THE SAME.
13640                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
13641                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
13642                 }
13643                 break;
13644         }
13645         // the only tcmod that needs software vertex processing is turbulent, so
13646         // check for it here and apply the changes if needed
13647         // and we only support that as the first one
13648         // (handling a mixture of turbulent and other tcmods would be problematic
13649         //  without punting it entirely to a software path)
13650         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
13651         {
13652                 amplitude = rsurface.texture->tcmods[0].parms[1];
13653                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
13654 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
13655 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
13656 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
13657                 for (j = 0;j < batchnumvertices;j++)
13658                 {
13659                         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);
13660                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
13661                 }
13662         }
13663
13664         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
13665         {
13666                 // convert the modified arrays to vertex structs
13667 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
13668 //              rsurface.batchvertexmeshbuffer = NULL;
13669                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
13670                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
13671                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
13672                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
13673                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
13674                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
13675                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
13676                 {
13677                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
13678                         {
13679                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
13680                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
13681                         }
13682                 }
13683                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
13684                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
13685                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
13686                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
13687                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
13688                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
13689                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
13690                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
13691                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
13692         }
13693 }
13694
13695 void RSurf_DrawBatch(void)
13696 {
13697         // sometimes a zero triangle surface (usually a degenerate patch) makes it
13698         // through the pipeline, killing it earlier in the pipeline would have
13699         // per-surface overhead rather than per-batch overhead, so it's best to
13700         // reject it here, before it hits glDraw.
13701         if (rsurface.batchnumtriangles == 0)
13702                 return;
13703 #if 0
13704         // batch debugging code
13705         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
13706         {
13707                 int i;
13708                 int j;
13709                 int c;
13710                 const int *e;
13711                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
13712                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
13713                 {
13714                         c = e[i];
13715                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
13716                         {
13717                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
13718                                 {
13719                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
13720                                                 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);
13721                                         break;
13722                                 }
13723                         }
13724                 }
13725         }
13726 #endif
13727         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);
13728 }
13729
13730 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
13731 {
13732         // pick the closest matching water plane
13733         int planeindex, vertexindex, bestplaneindex = -1;
13734         float d, bestd;
13735         vec3_t vert;
13736         const float *v;
13737         r_waterstate_waterplane_t *p;
13738         qboolean prepared = false;
13739         bestd = 0;
13740         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
13741         {
13742                 if(p->camera_entity != rsurface.texture->camera_entity)
13743                         continue;
13744                 d = 0;
13745                 if(!prepared)
13746                 {
13747                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
13748                         prepared = true;
13749                         if(rsurface.batchnumvertices == 0)
13750                                 break;
13751                 }
13752                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
13753                 {
13754                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
13755                         d += fabs(PlaneDiff(vert, &p->plane));
13756                 }
13757                 if (bestd > d || bestplaneindex < 0)
13758                 {
13759                         bestd = d;
13760                         bestplaneindex = planeindex;
13761                 }
13762         }
13763         return bestplaneindex;
13764         // NOTE: this MAY return a totally unrelated water plane; we can ignore
13765         // this situation though, as it might be better to render single larger
13766         // batches with useless stuff (backface culled for example) than to
13767         // render multiple smaller batches
13768 }
13769
13770 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
13771 {
13772         int i;
13773         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
13774         rsurface.passcolor4f_vertexbuffer = 0;
13775         rsurface.passcolor4f_bufferoffset = 0;
13776         for (i = 0;i < rsurface.batchnumvertices;i++)
13777                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
13778 }
13779
13780 static void RSurf_DrawBatch_GL11_ApplyFog(void)
13781 {
13782         int i;
13783         float f;
13784         const float *v;
13785         const float *c;
13786         float *c2;
13787         if (rsurface.passcolor4f)
13788         {
13789                 // generate color arrays
13790                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
13791                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
13792                 rsurface.passcolor4f_vertexbuffer = 0;
13793                 rsurface.passcolor4f_bufferoffset = 0;
13794                 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)
13795                 {
13796                         f = RSurf_FogVertex(v);
13797                         c2[0] = c[0] * f;
13798                         c2[1] = c[1] * f;
13799                         c2[2] = c[2] * f;
13800                         c2[3] = c[3];
13801                 }
13802         }
13803         else
13804         {
13805                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
13806                 rsurface.passcolor4f_vertexbuffer = 0;
13807                 rsurface.passcolor4f_bufferoffset = 0;
13808                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
13809                 {
13810                         f = RSurf_FogVertex(v);
13811                         c2[0] = f;
13812                         c2[1] = f;
13813                         c2[2] = f;
13814                         c2[3] = 1;
13815                 }
13816         }
13817 }
13818
13819 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
13820 {
13821         int i;
13822         float f;
13823         const float *v;
13824         const float *c;
13825         float *c2;
13826         if (!rsurface.passcolor4f)
13827                 return;
13828         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
13829         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
13830         rsurface.passcolor4f_vertexbuffer = 0;
13831         rsurface.passcolor4f_bufferoffset = 0;
13832         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)
13833         {
13834                 f = RSurf_FogVertex(v);
13835                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
13836                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
13837                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
13838                 c2[3] = c[3];
13839         }
13840 }
13841
13842 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
13843 {
13844         int i;
13845         const float *c;
13846         float *c2;
13847         if (!rsurface.passcolor4f)
13848                 return;
13849         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
13850         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
13851         rsurface.passcolor4f_vertexbuffer = 0;
13852         rsurface.passcolor4f_bufferoffset = 0;
13853         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
13854         {
13855                 c2[0] = c[0] * r;
13856                 c2[1] = c[1] * g;
13857                 c2[2] = c[2] * b;
13858                 c2[3] = c[3] * a;
13859         }
13860 }
13861
13862 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
13863 {
13864         int i;
13865         const float *c;
13866         float *c2;
13867         if (!rsurface.passcolor4f)
13868                 return;
13869         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
13870         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
13871         rsurface.passcolor4f_vertexbuffer = 0;
13872         rsurface.passcolor4f_bufferoffset = 0;
13873         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
13874         {
13875                 c2[0] = c[0] + r_refdef.scene.ambient;
13876                 c2[1] = c[1] + r_refdef.scene.ambient;
13877                 c2[2] = c[2] + r_refdef.scene.ambient;
13878                 c2[3] = c[3];
13879         }
13880 }
13881
13882 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
13883 {
13884         // TODO: optimize
13885         rsurface.passcolor4f = NULL;
13886         rsurface.passcolor4f_vertexbuffer = 0;
13887         rsurface.passcolor4f_bufferoffset = 0;
13888         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
13889         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
13890         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
13891         GL_Color(r, g, b, a);
13892         R_Mesh_TexBind(0, rsurface.lightmaptexture);
13893         RSurf_DrawBatch();
13894 }
13895
13896 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
13897 {
13898         // TODO: optimize applyfog && applycolor case
13899         // just apply fog if necessary, and tint the fog color array if necessary
13900         rsurface.passcolor4f = NULL;
13901         rsurface.passcolor4f_vertexbuffer = 0;
13902         rsurface.passcolor4f_bufferoffset = 0;
13903         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
13904         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
13905         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
13906         GL_Color(r, g, b, a);
13907         RSurf_DrawBatch();
13908 }
13909
13910 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
13911 {
13912         // TODO: optimize
13913         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
13914         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
13915         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
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_ClampColor(void)
13924 {
13925         int i;
13926         const float *c1;
13927         float *c2;
13928         if (!rsurface.passcolor4f)
13929                 return;
13930         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
13931         {
13932                 c2[0] = bound(0.0f, c1[0], 1.0f);
13933                 c2[1] = bound(0.0f, c1[1], 1.0f);
13934                 c2[2] = bound(0.0f, c1[2], 1.0f);
13935                 c2[3] = bound(0.0f, c1[3], 1.0f);
13936         }
13937 }
13938
13939 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
13940 {
13941         int i;
13942         float f;
13943         const float *v;
13944         const float *n;
13945         float *c;
13946         //vec3_t eyedir;
13947
13948         // fake shading
13949         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
13950         rsurface.passcolor4f_vertexbuffer = 0;
13951         rsurface.passcolor4f_bufferoffset = 0;
13952         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)
13953         {
13954                 f = -DotProduct(r_refdef.view.forward, n);
13955                 f = max(0, f);
13956                 f = f * 0.85 + 0.15; // work around so stuff won't get black
13957                 f *= r_refdef.lightmapintensity;
13958                 Vector4Set(c, f, f, f, 1);
13959         }
13960 }
13961
13962 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
13963 {
13964         RSurf_DrawBatch_GL11_ApplyFakeLight();
13965         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
13966         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
13967         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
13968         GL_Color(r, g, b, a);
13969         RSurf_DrawBatch();
13970 }
13971
13972 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
13973 {
13974         int i;
13975         float f;
13976         float alpha;
13977         const float *v;
13978         const float *n;
13979         float *c;
13980         vec3_t ambientcolor;
13981         vec3_t diffusecolor;
13982         vec3_t lightdir;
13983         // TODO: optimize
13984         // model lighting
13985         VectorCopy(rsurface.modellight_lightdir, lightdir);
13986         f = 0.5f * r_refdef.lightmapintensity;
13987         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
13988         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
13989         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
13990         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
13991         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
13992         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
13993         alpha = *a;
13994         if (VectorLength2(diffusecolor) > 0)
13995         {
13996                 // q3-style directional shading
13997                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
13998                 rsurface.passcolor4f_vertexbuffer = 0;
13999                 rsurface.passcolor4f_bufferoffset = 0;
14000                 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)
14001                 {
14002                         if ((f = DotProduct(n, lightdir)) > 0)
14003                                 VectorMA(ambientcolor, f, diffusecolor, c);
14004                         else
14005                                 VectorCopy(ambientcolor, c);
14006                         c[3] = alpha;
14007                 }
14008                 *r = 1;
14009                 *g = 1;
14010                 *b = 1;
14011                 *a = 1;
14012                 *applycolor = false;
14013         }
14014         else
14015         {
14016                 *r = ambientcolor[0];
14017                 *g = ambientcolor[1];
14018                 *b = ambientcolor[2];
14019                 rsurface.passcolor4f = NULL;
14020                 rsurface.passcolor4f_vertexbuffer = 0;
14021                 rsurface.passcolor4f_bufferoffset = 0;
14022         }
14023 }
14024
14025 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
14026 {
14027         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
14028         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
14029         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
14030         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
14031         GL_Color(r, g, b, a);
14032         RSurf_DrawBatch();
14033 }
14034
14035 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
14036 {
14037         int i;
14038         float f;
14039         const float *v;
14040         float *c;
14041         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
14042         {
14043                 f = 1 - RSurf_FogVertex(v);
14044                 c[0] = r;
14045                 c[1] = g;
14046                 c[2] = b;
14047                 c[3] = f * a;
14048         }
14049 }
14050
14051 void RSurf_SetupDepthAndCulling(void)
14052 {
14053         // submodels are biased to avoid z-fighting with world surfaces that they
14054         // may be exactly overlapping (avoids z-fighting artifacts on certain
14055         // doors and things in Quake maps)
14056         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
14057         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
14058         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
14059         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
14060 }
14061
14062 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
14063 {
14064         // transparent sky would be ridiculous
14065         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
14066                 return;
14067         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14068         skyrenderlater = true;
14069         RSurf_SetupDepthAndCulling();
14070         GL_DepthMask(true);
14071         // LordHavoc: HalfLife maps have freaky skypolys so don't use
14072         // skymasking on them, and Quake3 never did sky masking (unlike
14073         // software Quake and software Quake2), so disable the sky masking
14074         // in Quake3 maps as it causes problems with q3map2 sky tricks,
14075         // and skymasking also looks very bad when noclipping outside the
14076         // level, so don't use it then either.
14077         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
14078         {
14079                 R_Mesh_ResetTextureState();
14080                 if (skyrendermasked)
14081                 {
14082                         R_SetupShader_DepthOrShadow();
14083                         // depth-only (masking)
14084                         GL_ColorMask(0,0,0,0);
14085                         // just to make sure that braindead drivers don't draw
14086                         // anything despite that colormask...
14087                         GL_BlendFunc(GL_ZERO, GL_ONE);
14088                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
14089                         if (rsurface.batchvertex3fbuffer)
14090                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
14091                         else
14092                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
14093                 }
14094                 else
14095                 {
14096                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14097                         // fog sky
14098                         GL_BlendFunc(GL_ONE, GL_ZERO);
14099                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
14100                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
14101                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14102                 }
14103                 RSurf_DrawBatch();
14104                 if (skyrendermasked)
14105                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
14106         }
14107         R_Mesh_ResetTextureState();
14108         GL_Color(1, 1, 1, 1);
14109 }
14110
14111 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
14112 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
14113 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
14114 {
14115         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
14116                 return;
14117         if (prepass)
14118         {
14119                 // render screenspace normalmap to texture
14120                 GL_DepthMask(true);
14121                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
14122                 RSurf_DrawBatch();
14123                 return;
14124         }
14125
14126         // bind lightmap texture
14127
14128         // water/refraction/reflection/camera surfaces have to be handled specially
14129         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
14130         {
14131                 int start, end, startplaneindex;
14132                 for (start = 0;start < texturenumsurfaces;start = end)
14133                 {
14134                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
14135                         if(startplaneindex < 0)
14136                         {
14137                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
14138                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
14139                                 end = start + 1;
14140                                 continue;
14141                         }
14142                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
14143                                 ;
14144                         // now that we have a batch using the same planeindex, render it
14145                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
14146                         {
14147                                 // render water or distortion background
14148                                 GL_DepthMask(true);
14149                                 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));
14150                                 RSurf_DrawBatch();
14151                                 // blend surface on top
14152                                 GL_DepthMask(false);
14153                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
14154                                 RSurf_DrawBatch();
14155                         }
14156                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
14157                         {
14158                                 // render surface with reflection texture as input
14159                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
14160                                 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));
14161                                 RSurf_DrawBatch();
14162                         }
14163                 }
14164                 return;
14165         }
14166
14167         // render surface batch normally
14168         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
14169         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
14170         RSurf_DrawBatch();
14171 }
14172
14173 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
14174 {
14175         // OpenGL 1.3 path - anything not completely ancient
14176         qboolean applycolor;
14177         qboolean applyfog;
14178         int layerindex;
14179         const texturelayer_t *layer;
14180         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);
14181         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
14182
14183         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
14184         {
14185                 vec4_t layercolor;
14186                 int layertexrgbscale;
14187                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
14188                 {
14189                         if (layerindex == 0)
14190                                 GL_AlphaTest(true);
14191                         else
14192                         {
14193                                 GL_AlphaTest(false);
14194                                 GL_DepthFunc(GL_EQUAL);
14195                         }
14196                 }
14197                 GL_DepthMask(layer->depthmask && writedepth);
14198                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
14199                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
14200                 {
14201                         layertexrgbscale = 4;
14202                         VectorScale(layer->color, 0.25f, layercolor);
14203                 }
14204                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
14205                 {
14206                         layertexrgbscale = 2;
14207                         VectorScale(layer->color, 0.5f, layercolor);
14208                 }
14209                 else
14210                 {
14211                         layertexrgbscale = 1;
14212                         VectorScale(layer->color, 1.0f, layercolor);
14213                 }
14214                 layercolor[3] = layer->color[3];
14215                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
14216                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
14217                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
14218                 switch (layer->type)
14219                 {
14220                 case TEXTURELAYERTYPE_LITTEXTURE:
14221                         // single-pass lightmapped texture with 2x rgbscale
14222                         R_Mesh_TexBind(0, r_texture_white);
14223                         R_Mesh_TexMatrix(0, NULL);
14224                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
14225                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
14226                         R_Mesh_TexBind(1, layer->texture);
14227                         R_Mesh_TexMatrix(1, &layer->texmatrix);
14228                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
14229                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
14230                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
14231                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
14232                         else if (FAKELIGHT_ENABLED)
14233                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
14234                         else if (rsurface.uselightmaptexture)
14235                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
14236                         else
14237                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
14238                         break;
14239                 case TEXTURELAYERTYPE_TEXTURE:
14240                         // singletexture unlit texture with transparency support
14241                         R_Mesh_TexBind(0, layer->texture);
14242                         R_Mesh_TexMatrix(0, &layer->texmatrix);
14243                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
14244                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
14245                         R_Mesh_TexBind(1, 0);
14246                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
14247                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
14248                         break;
14249                 case TEXTURELAYERTYPE_FOG:
14250                         // singletexture fogging
14251                         if (layer->texture)
14252                         {
14253                                 R_Mesh_TexBind(0, layer->texture);
14254                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
14255                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
14256                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
14257                         }
14258                         else
14259                         {
14260                                 R_Mesh_TexBind(0, 0);
14261                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
14262                         }
14263                         R_Mesh_TexBind(1, 0);
14264                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
14265                         // generate a color array for the fog pass
14266                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
14267                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
14268                         RSurf_DrawBatch();
14269                         break;
14270                 default:
14271                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
14272                 }
14273         }
14274         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
14275         {
14276                 GL_DepthFunc(GL_LEQUAL);
14277                 GL_AlphaTest(false);
14278         }
14279 }
14280
14281 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
14282 {
14283         // OpenGL 1.1 - crusty old voodoo path
14284         qboolean applyfog;
14285         int layerindex;
14286         const texturelayer_t *layer;
14287         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);
14288         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
14289
14290         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
14291         {
14292                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
14293                 {
14294                         if (layerindex == 0)
14295                                 GL_AlphaTest(true);
14296                         else
14297                         {
14298                                 GL_AlphaTest(false);
14299                                 GL_DepthFunc(GL_EQUAL);
14300                         }
14301                 }
14302                 GL_DepthMask(layer->depthmask && writedepth);
14303                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
14304                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
14305                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
14306                 switch (layer->type)
14307                 {
14308                 case TEXTURELAYERTYPE_LITTEXTURE:
14309                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
14310                         {
14311                                 // two-pass lit texture with 2x rgbscale
14312                                 // first the lightmap pass
14313                                 R_Mesh_TexBind(0, r_texture_white);
14314                                 R_Mesh_TexMatrix(0, NULL);
14315                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
14316                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
14317                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
14318                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
14319                                 else if (FAKELIGHT_ENABLED)
14320                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
14321                                 else if (rsurface.uselightmaptexture)
14322                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
14323                                 else
14324                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
14325                                 // then apply the texture to it
14326                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
14327                                 R_Mesh_TexBind(0, layer->texture);
14328                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
14329                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
14330                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
14331                                 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);
14332                         }
14333                         else
14334                         {
14335                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
14336                                 R_Mesh_TexBind(0, layer->texture);
14337                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
14338                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
14339                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
14340                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
14341                                         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);
14342                                 else
14343                                         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);
14344                         }
14345                         break;
14346                 case TEXTURELAYERTYPE_TEXTURE:
14347                         // singletexture unlit texture with transparency support
14348                         R_Mesh_TexBind(0, layer->texture);
14349                         R_Mesh_TexMatrix(0, &layer->texmatrix);
14350                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
14351                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
14352                         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);
14353                         break;
14354                 case TEXTURELAYERTYPE_FOG:
14355                         // singletexture fogging
14356                         if (layer->texture)
14357                         {
14358                                 R_Mesh_TexBind(0, layer->texture);
14359                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
14360                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
14361                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
14362                         }
14363                         else
14364                         {
14365                                 R_Mesh_TexBind(0, 0);
14366                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
14367                         }
14368                         // generate a color array for the fog pass
14369                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
14370                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
14371                         RSurf_DrawBatch();
14372                         break;
14373                 default:
14374                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
14375                 }
14376         }
14377         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
14378         {
14379                 GL_DepthFunc(GL_LEQUAL);
14380                 GL_AlphaTest(false);
14381         }
14382 }
14383
14384 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
14385 {
14386         int vi;
14387         int j;
14388         r_vertexgeneric_t *batchvertex;
14389         float c[4];
14390
14391         GL_AlphaTest(false);
14392 //      R_Mesh_ResetTextureState();
14393         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14394
14395         if(rsurface.texture && rsurface.texture->currentskinframe)
14396         {
14397                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
14398                 c[3] *= rsurface.texture->currentalpha;
14399         }
14400         else
14401         {
14402                 c[0] = 1;
14403                 c[1] = 0;
14404                 c[2] = 1;
14405                 c[3] = 1;
14406         }
14407
14408         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
14409         {
14410                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
14411                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
14412                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
14413         }
14414
14415         // brighten it up (as texture value 127 means "unlit")
14416         c[0] *= 2 * r_refdef.view.colorscale;
14417         c[1] *= 2 * r_refdef.view.colorscale;
14418         c[2] *= 2 * r_refdef.view.colorscale;
14419
14420         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
14421                 c[3] *= r_wateralpha.value;
14422
14423         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
14424         {
14425                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14426                 GL_DepthMask(false);
14427         }
14428         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
14429         {
14430                 GL_BlendFunc(GL_ONE, GL_ONE);
14431                 GL_DepthMask(false);
14432         }
14433         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
14434         {
14435                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
14436                 GL_DepthMask(false);
14437         }
14438         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
14439         {
14440                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
14441                 GL_DepthMask(false);
14442         }
14443         else
14444         {
14445                 GL_BlendFunc(GL_ONE, GL_ZERO);
14446                 GL_DepthMask(writedepth);
14447         }
14448
14449         if (r_showsurfaces.integer == 3)
14450         {
14451                 rsurface.passcolor4f = NULL;
14452
14453                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
14454                 {
14455                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
14456
14457                         rsurface.passcolor4f = NULL;
14458                         rsurface.passcolor4f_vertexbuffer = 0;
14459                         rsurface.passcolor4f_bufferoffset = 0;
14460                 }
14461                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
14462                 {
14463                         qboolean applycolor = true;
14464                         float one = 1.0;
14465
14466                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
14467
14468                         r_refdef.lightmapintensity = 1;
14469                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
14470                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
14471                 }
14472                 else if (FAKELIGHT_ENABLED)
14473                 {
14474                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
14475
14476                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
14477                         RSurf_DrawBatch_GL11_ApplyFakeLight();
14478                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
14479                 }
14480                 else
14481                 {
14482                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
14483
14484                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
14485                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
14486                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
14487                 }
14488
14489                 if(!rsurface.passcolor4f)
14490                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
14491
14492                 RSurf_DrawBatch_GL11_ApplyAmbient();
14493                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
14494                 if(r_refdef.fogenabled)
14495                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
14496                 RSurf_DrawBatch_GL11_ClampColor();
14497
14498                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
14499                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14500                 RSurf_DrawBatch();
14501         }
14502         else if (!r_refdef.view.showdebug)
14503         {
14504                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
14505                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
14506                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
14507                 {
14508                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
14509                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
14510                 }
14511                 R_Mesh_PrepareVertices_Generic_Unlock();
14512                 RSurf_DrawBatch();
14513         }
14514         else if (r_showsurfaces.integer == 4)
14515         {
14516                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
14517                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
14518                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
14519                 {
14520                         unsigned char c = vi << 3;
14521                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
14522                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
14523                 }
14524                 R_Mesh_PrepareVertices_Generic_Unlock();
14525                 RSurf_DrawBatch();
14526         }
14527         else if (r_showsurfaces.integer == 2)
14528         {
14529                 const int *e;
14530                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
14531                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
14532                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
14533                 {
14534                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
14535                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
14536                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
14537                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
14538                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
14539                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
14540                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
14541                 }
14542                 R_Mesh_PrepareVertices_Generic_Unlock();
14543                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
14544         }
14545         else
14546         {
14547                 int texturesurfaceindex;
14548                 int k;
14549                 const msurface_t *surface;
14550                 unsigned char surfacecolor4ub[4];
14551                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
14552                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
14553                 vi = 0;
14554                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
14555                 {
14556                         surface = texturesurfacelist[texturesurfaceindex];
14557                         k = (int)(((size_t)surface) / sizeof(msurface_t));
14558                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
14559                         for (j = 0;j < surface->num_vertices;j++)
14560                         {
14561                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
14562                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
14563                                 vi++;
14564                         }
14565                 }
14566                 R_Mesh_PrepareVertices_Generic_Unlock();
14567                 RSurf_DrawBatch();
14568         }
14569 }
14570
14571 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
14572 {
14573         CHECKGLERROR
14574         RSurf_SetupDepthAndCulling();
14575         if (r_showsurfaces.integer)
14576         {
14577                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
14578                 return;
14579         }
14580         switch (vid.renderpath)
14581         {
14582         case RENDERPATH_GL20:
14583         case RENDERPATH_CGGL:
14584         case RENDERPATH_D3D9:
14585         case RENDERPATH_D3D10:
14586         case RENDERPATH_D3D11:
14587         case RENDERPATH_SOFT:
14588         case RENDERPATH_GLES2:
14589                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
14590                 break;
14591         case RENDERPATH_GL13:
14592                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
14593                 break;
14594         case RENDERPATH_GL11:
14595                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
14596                 break;
14597         }
14598         CHECKGLERROR
14599 }
14600
14601 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
14602 {
14603         CHECKGLERROR
14604         RSurf_SetupDepthAndCulling();
14605         if (r_showsurfaces.integer)
14606         {
14607                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
14608                 return;
14609         }
14610         switch (vid.renderpath)
14611         {
14612         case RENDERPATH_GL20:
14613         case RENDERPATH_CGGL:
14614         case RENDERPATH_D3D9:
14615         case RENDERPATH_D3D10:
14616         case RENDERPATH_D3D11:
14617         case RENDERPATH_SOFT:
14618         case RENDERPATH_GLES2:
14619                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
14620                 break;
14621         case RENDERPATH_GL13:
14622                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
14623                 break;
14624         case RENDERPATH_GL11:
14625                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
14626                 break;
14627         }
14628         CHECKGLERROR
14629 }
14630
14631 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
14632 {
14633         int i, j;
14634         int texturenumsurfaces, endsurface;
14635         texture_t *texture;
14636         const msurface_t *surface;
14637 #define MAXBATCH_TRANSPARENTSURFACES 256
14638         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
14639
14640         // if the model is static it doesn't matter what value we give for
14641         // wantnormals and wanttangents, so this logic uses only rules applicable
14642         // to a model, knowing that they are meaningless otherwise
14643         if (ent == r_refdef.scene.worldentity)
14644                 RSurf_ActiveWorldEntity();
14645         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14646                 RSurf_ActiveModelEntity(ent, false, false, false);
14647         else
14648         {
14649                 switch (vid.renderpath)
14650                 {
14651                 case RENDERPATH_GL20:
14652                 case RENDERPATH_CGGL:
14653                 case RENDERPATH_D3D9:
14654                 case RENDERPATH_D3D10:
14655                 case RENDERPATH_D3D11:
14656                 case RENDERPATH_SOFT:
14657                 case RENDERPATH_GLES2:
14658                         RSurf_ActiveModelEntity(ent, true, true, false);
14659                         break;
14660                 case RENDERPATH_GL13:
14661                 case RENDERPATH_GL11:
14662                         RSurf_ActiveModelEntity(ent, true, false, false);
14663                         break;
14664                 }
14665         }
14666
14667         if (r_transparentdepthmasking.integer)
14668         {
14669                 qboolean setup = false;
14670                 for (i = 0;i < numsurfaces;i = j)
14671                 {
14672                         j = i + 1;
14673                         surface = rsurface.modelsurfaces + surfacelist[i];
14674                         texture = surface->texture;
14675                         rsurface.texture = R_GetCurrentTexture(texture);
14676                         rsurface.lightmaptexture = NULL;
14677                         rsurface.deluxemaptexture = NULL;
14678                         rsurface.uselightmaptexture = false;
14679                         // scan ahead until we find a different texture
14680                         endsurface = min(i + 1024, numsurfaces);
14681                         texturenumsurfaces = 0;
14682                         texturesurfacelist[texturenumsurfaces++] = surface;
14683                         for (;j < endsurface;j++)
14684                         {
14685                                 surface = rsurface.modelsurfaces + surfacelist[j];
14686                                 if (texture != surface->texture)
14687                                         break;
14688                                 texturesurfacelist[texturenumsurfaces++] = surface;
14689                         }
14690                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
14691                                 continue;
14692                         // render the range of surfaces as depth
14693                         if (!setup)
14694                         {
14695                                 setup = true;
14696                                 GL_ColorMask(0,0,0,0);
14697                                 GL_Color(1,1,1,1);
14698                                 GL_DepthTest(true);
14699                                 GL_BlendFunc(GL_ONE, GL_ZERO);
14700                                 GL_DepthMask(true);
14701                                 GL_AlphaTest(false);
14702 //                              R_Mesh_ResetTextureState();
14703                                 R_SetupShader_DepthOrShadow();
14704                         }
14705                         RSurf_SetupDepthAndCulling();
14706                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
14707                         if (rsurface.batchvertex3fbuffer)
14708                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
14709                         else
14710                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
14711                         RSurf_DrawBatch();
14712                 }
14713                 if (setup)
14714                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
14715         }
14716
14717         for (i = 0;i < numsurfaces;i = j)
14718         {
14719                 j = i + 1;
14720                 surface = rsurface.modelsurfaces + surfacelist[i];
14721                 texture = surface->texture;
14722                 rsurface.texture = R_GetCurrentTexture(texture);
14723                 // scan ahead until we find a different texture
14724                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
14725                 texturenumsurfaces = 0;
14726                 texturesurfacelist[texturenumsurfaces++] = surface;
14727                 if(FAKELIGHT_ENABLED)
14728                 {
14729                         rsurface.lightmaptexture = NULL;
14730                         rsurface.deluxemaptexture = NULL;
14731                         rsurface.uselightmaptexture = false;
14732                         for (;j < endsurface;j++)
14733                         {
14734                                 surface = rsurface.modelsurfaces + surfacelist[j];
14735                                 if (texture != surface->texture)
14736                                         break;
14737                                 texturesurfacelist[texturenumsurfaces++] = surface;
14738                         }
14739                 }
14740                 else
14741                 {
14742                         rsurface.lightmaptexture = surface->lightmaptexture;
14743                         rsurface.deluxemaptexture = surface->deluxemaptexture;
14744                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
14745                         for (;j < endsurface;j++)
14746                         {
14747                                 surface = rsurface.modelsurfaces + surfacelist[j];
14748                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
14749                                         break;
14750                                 texturesurfacelist[texturenumsurfaces++] = surface;
14751                         }
14752                 }
14753                 // render the range of surfaces
14754                 if (ent == r_refdef.scene.worldentity)
14755                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
14756                 else
14757                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
14758         }
14759         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14760         GL_AlphaTest(false);
14761 }
14762
14763 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
14764 {
14765         // transparent surfaces get pushed off into the transparent queue
14766         int surfacelistindex;
14767         const msurface_t *surface;
14768         vec3_t tempcenter, center;
14769         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
14770         {
14771                 surface = texturesurfacelist[surfacelistindex];
14772                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
14773                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
14774                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
14775                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
14776                 if (queueentity->transparent_offset) // transparent offset
14777                 {
14778                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
14779                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
14780                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
14781                 }
14782                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
14783         }
14784 }
14785
14786 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
14787 {
14788         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
14789                 return;
14790         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
14791                 return;
14792         RSurf_SetupDepthAndCulling();
14793         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
14794         if (rsurface.batchvertex3fbuffer)
14795                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
14796         else
14797                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
14798         RSurf_DrawBatch();
14799 }
14800
14801 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
14802 {
14803         const entity_render_t *queueentity = r_refdef.scene.worldentity;
14804         CHECKGLERROR
14805         if (depthonly)
14806                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
14807         else if (prepass)
14808         {
14809                 if (!rsurface.texture->currentnumlayers)
14810                         return;
14811                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
14812                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
14813                 else
14814                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
14815         }
14816         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
14817                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
14818         else if (!rsurface.texture->currentnumlayers)
14819                 return;
14820         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
14821         {
14822                 // in the deferred case, transparent surfaces were queued during prepass
14823                 if (!r_shadow_usingdeferredprepass)
14824                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
14825         }
14826         else
14827         {
14828                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
14829                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
14830         }
14831         CHECKGLERROR
14832 }
14833
14834 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
14835 {
14836         int i, j;
14837         texture_t *texture;
14838         R_FrameData_SetMark();
14839         // break the surface list down into batches by texture and use of lightmapping
14840         for (i = 0;i < numsurfaces;i = j)
14841         {
14842                 j = i + 1;
14843                 // texture is the base texture pointer, rsurface.texture is the
14844                 // current frame/skin the texture is directing us to use (for example
14845                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
14846                 // use skin 1 instead)
14847                 texture = surfacelist[i]->texture;
14848                 rsurface.texture = R_GetCurrentTexture(texture);
14849                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
14850                 {
14851                         // if this texture is not the kind we want, skip ahead to the next one
14852                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
14853                                 ;
14854                         continue;
14855                 }
14856                 if(FAKELIGHT_ENABLED || depthonly || prepass)
14857                 {
14858                         rsurface.lightmaptexture = NULL;
14859                         rsurface.deluxemaptexture = NULL;
14860                         rsurface.uselightmaptexture = false;
14861                         // simply scan ahead until we find a different texture or lightmap state
14862                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
14863                                 ;
14864                 }
14865                 else
14866                 {
14867                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
14868                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
14869                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
14870                         // simply scan ahead until we find a different texture or lightmap state
14871                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
14872                                 ;
14873                 }
14874                 // render the range of surfaces
14875                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
14876         }
14877         R_FrameData_ReturnToMark();
14878 }
14879
14880 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
14881 {
14882         CHECKGLERROR
14883         if (depthonly)
14884                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
14885         else if (prepass)
14886         {
14887                 if (!rsurface.texture->currentnumlayers)
14888                         return;
14889                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
14890                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
14891                 else
14892                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
14893         }
14894         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
14895                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
14896         else if (!rsurface.texture->currentnumlayers)
14897                 return;
14898         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
14899         {
14900                 // in the deferred case, transparent surfaces were queued during prepass
14901                 if (!r_shadow_usingdeferredprepass)
14902                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
14903         }
14904         else
14905         {
14906                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
14907                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
14908         }
14909         CHECKGLERROR
14910 }
14911
14912 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
14913 {
14914         int i, j;
14915         texture_t *texture;
14916         R_FrameData_SetMark();
14917         // break the surface list down into batches by texture and use of lightmapping
14918         for (i = 0;i < numsurfaces;i = j)
14919         {
14920                 j = i + 1;
14921                 // texture is the base texture pointer, rsurface.texture is the
14922                 // current frame/skin the texture is directing us to use (for example
14923                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
14924                 // use skin 1 instead)
14925                 texture = surfacelist[i]->texture;
14926                 rsurface.texture = R_GetCurrentTexture(texture);
14927                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
14928                 {
14929                         // if this texture is not the kind we want, skip ahead to the next one
14930                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
14931                                 ;
14932                         continue;
14933                 }
14934                 if(FAKELIGHT_ENABLED || depthonly || prepass)
14935                 {
14936                         rsurface.lightmaptexture = NULL;
14937                         rsurface.deluxemaptexture = NULL;
14938                         rsurface.uselightmaptexture = false;
14939                         // simply scan ahead until we find a different texture or lightmap state
14940                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
14941                                 ;
14942                 }
14943                 else
14944                 {
14945                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
14946                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
14947                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
14948                         // simply scan ahead until we find a different texture or lightmap state
14949                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
14950                                 ;
14951                 }
14952                 // render the range of surfaces
14953                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
14954         }
14955         R_FrameData_ReturnToMark();
14956 }
14957
14958 float locboxvertex3f[6*4*3] =
14959 {
14960         1,0,1, 1,0,0, 1,1,0, 1,1,1,
14961         0,1,1, 0,1,0, 0,0,0, 0,0,1,
14962         1,1,1, 1,1,0, 0,1,0, 0,1,1,
14963         0,0,1, 0,0,0, 1,0,0, 1,0,1,
14964         0,0,1, 1,0,1, 1,1,1, 0,1,1,
14965         1,0,0, 0,0,0, 0,1,0, 1,1,0
14966 };
14967
14968 unsigned short locboxelements[6*2*3] =
14969 {
14970          0, 1, 2, 0, 2, 3,
14971          4, 5, 6, 4, 6, 7,
14972          8, 9,10, 8,10,11,
14973         12,13,14, 12,14,15,
14974         16,17,18, 16,18,19,
14975         20,21,22, 20,22,23
14976 };
14977
14978 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
14979 {
14980         int i, j;
14981         cl_locnode_t *loc = (cl_locnode_t *)ent;
14982         vec3_t mins, size;
14983         float vertex3f[6*4*3];
14984         CHECKGLERROR
14985         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14986         GL_DepthMask(false);
14987         GL_DepthRange(0, 1);
14988         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14989         GL_DepthTest(true);
14990         GL_CullFace(GL_NONE);
14991         R_EntityMatrix(&identitymatrix);
14992
14993 //      R_Mesh_ResetTextureState();
14994
14995         i = surfacelist[0];
14996         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
14997                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
14998                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
14999                         surfacelist[0] < 0 ? 0.5f : 0.125f);
15000
15001         if (VectorCompare(loc->mins, loc->maxs))
15002         {
15003                 VectorSet(size, 2, 2, 2);
15004                 VectorMA(loc->mins, -0.5f, size, mins);
15005         }
15006         else
15007         {
15008                 VectorCopy(loc->mins, mins);
15009                 VectorSubtract(loc->maxs, loc->mins, size);
15010         }
15011
15012         for (i = 0;i < 6*4*3;)
15013                 for (j = 0;j < 3;j++, i++)
15014                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
15015
15016         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
15017         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
15018         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
15019 }
15020
15021 void R_DrawLocs(void)
15022 {
15023         int index;
15024         cl_locnode_t *loc, *nearestloc;
15025         vec3_t center;
15026         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
15027         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
15028         {
15029                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
15030                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
15031         }
15032 }
15033
15034 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
15035 {
15036         if (decalsystem->decals)
15037                 Mem_Free(decalsystem->decals);
15038         memset(decalsystem, 0, sizeof(*decalsystem));
15039 }
15040
15041 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)
15042 {
15043         tridecal_t *decal;
15044         tridecal_t *decals;
15045         int i;
15046
15047         // expand or initialize the system
15048         if (decalsystem->maxdecals <= decalsystem->numdecals)
15049         {
15050                 decalsystem_t old = *decalsystem;
15051                 qboolean useshortelements;
15052                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
15053                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
15054                 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)));
15055                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
15056                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
15057                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
15058                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
15059                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
15060                 if (decalsystem->numdecals)
15061                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
15062                 if (old.decals)
15063                         Mem_Free(old.decals);
15064                 for (i = 0;i < decalsystem->maxdecals*3;i++)
15065                         decalsystem->element3i[i] = i;
15066                 if (useshortelements)
15067                         for (i = 0;i < decalsystem->maxdecals*3;i++)
15068                                 decalsystem->element3s[i] = i;
15069         }
15070
15071         // grab a decal and search for another free slot for the next one
15072         decals = decalsystem->decals;
15073         decal = decalsystem->decals + (i = decalsystem->freedecal++);
15074         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
15075                 ;
15076         decalsystem->freedecal = i;
15077         if (decalsystem->numdecals <= i)
15078                 decalsystem->numdecals = i + 1;
15079
15080         // initialize the decal
15081         decal->lived = 0;
15082         decal->triangleindex = triangleindex;
15083         decal->surfaceindex = surfaceindex;
15084         decal->decalsequence = decalsequence;
15085         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
15086         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
15087         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
15088         decal->color4ub[0][3] = 255;
15089         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
15090         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
15091         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
15092         decal->color4ub[1][3] = 255;
15093         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
15094         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
15095         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
15096         decal->color4ub[2][3] = 255;
15097         decal->vertex3f[0][0] = v0[0];
15098         decal->vertex3f[0][1] = v0[1];
15099         decal->vertex3f[0][2] = v0[2];
15100         decal->vertex3f[1][0] = v1[0];
15101         decal->vertex3f[1][1] = v1[1];
15102         decal->vertex3f[1][2] = v1[2];
15103         decal->vertex3f[2][0] = v2[0];
15104         decal->vertex3f[2][1] = v2[1];
15105         decal->vertex3f[2][2] = v2[2];
15106         decal->texcoord2f[0][0] = t0[0];
15107         decal->texcoord2f[0][1] = t0[1];
15108         decal->texcoord2f[1][0] = t1[0];
15109         decal->texcoord2f[1][1] = t1[1];
15110         decal->texcoord2f[2][0] = t2[0];
15111         decal->texcoord2f[2][1] = t2[1];
15112 }
15113
15114 extern cvar_t cl_decals_bias;
15115 extern cvar_t cl_decals_models;
15116 extern cvar_t cl_decals_newsystem_intensitymultiplier;
15117 // baseparms, parms, temps
15118 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)
15119 {
15120         int cornerindex;
15121         int index;
15122         float v[9][3];
15123         const float *vertex3f;
15124         int numpoints;
15125         float points[2][9][3];
15126         float temp[3];
15127         float tc[9][2];
15128         float f;
15129         float c[9][4];
15130         const int *e;
15131
15132         e = rsurface.modelelement3i + 3*triangleindex;
15133
15134         vertex3f = rsurface.modelvertex3f;
15135
15136         for (cornerindex = 0;cornerindex < 3;cornerindex++)
15137         {
15138                 index = 3*e[cornerindex];
15139                 VectorCopy(vertex3f + index, v[cornerindex]);
15140         }
15141         // cull backfaces
15142         //TriangleNormal(v[0], v[1], v[2], normal);
15143         //if (DotProduct(normal, localnormal) < 0.0f)
15144         //      continue;
15145         // clip by each of the box planes formed from the projection matrix
15146         // if anything survives, we emit the decal
15147         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]);
15148         if (numpoints < 3)
15149                 return;
15150         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]);
15151         if (numpoints < 3)
15152                 return;
15153         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]);
15154         if (numpoints < 3)
15155                 return;
15156         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]);
15157         if (numpoints < 3)
15158                 return;
15159         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]);
15160         if (numpoints < 3)
15161                 return;
15162         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]);
15163         if (numpoints < 3)
15164                 return;
15165         // some part of the triangle survived, so we have to accept it...
15166         if (dynamic)
15167         {
15168                 // dynamic always uses the original triangle
15169                 numpoints = 3;
15170                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
15171                 {
15172                         index = 3*e[cornerindex];
15173                         VectorCopy(vertex3f + index, v[cornerindex]);
15174                 }
15175         }
15176         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
15177         {
15178                 // convert vertex positions to texcoords
15179                 Matrix4x4_Transform(projection, v[cornerindex], temp);
15180                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
15181                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
15182                 // calculate distance fade from the projection origin
15183                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
15184                 f = bound(0.0f, f, 1.0f);
15185                 c[cornerindex][0] = r * f;
15186                 c[cornerindex][1] = g * f;
15187                 c[cornerindex][2] = b * f;
15188                 c[cornerindex][3] = 1.0f;
15189                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
15190         }
15191         if (dynamic)
15192                 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);
15193         else
15194                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
15195                         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);
15196 }
15197 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)
15198 {
15199         matrix4x4_t projection;
15200         decalsystem_t *decalsystem;
15201         qboolean dynamic;
15202         dp_model_t *model;
15203         const msurface_t *surface;
15204         const msurface_t *surfaces;
15205         const int *surfacelist;
15206         const texture_t *texture;
15207         int numtriangles;
15208         int numsurfacelist;
15209         int surfacelistindex;
15210         int surfaceindex;
15211         int triangleindex;
15212         float localorigin[3];
15213         float localnormal[3];
15214         float localmins[3];
15215         float localmaxs[3];
15216         float localsize;
15217         //float normal[3];
15218         float planes[6][4];
15219         float angles[3];
15220         bih_t *bih;
15221         int bih_triangles_count;
15222         int bih_triangles[256];
15223         int bih_surfaces[256];
15224
15225         decalsystem = &ent->decalsystem;
15226         model = ent->model;
15227         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
15228         {
15229                 R_DecalSystem_Reset(&ent->decalsystem);
15230                 return;
15231         }
15232
15233         if (!model->brush.data_leafs && !cl_decals_models.integer)
15234         {
15235                 if (decalsystem->model)
15236                         R_DecalSystem_Reset(decalsystem);
15237                 return;
15238         }
15239
15240         if (decalsystem->model != model)
15241                 R_DecalSystem_Reset(decalsystem);
15242         decalsystem->model = model;
15243
15244         RSurf_ActiveModelEntity(ent, false, false, false);
15245
15246         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
15247         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
15248         VectorNormalize(localnormal);
15249         localsize = worldsize*rsurface.inversematrixscale;
15250         localmins[0] = localorigin[0] - localsize;
15251         localmins[1] = localorigin[1] - localsize;
15252         localmins[2] = localorigin[2] - localsize;
15253         localmaxs[0] = localorigin[0] + localsize;
15254         localmaxs[1] = localorigin[1] + localsize;
15255         localmaxs[2] = localorigin[2] + localsize;
15256
15257         //VectorCopy(localnormal, planes[4]);
15258         //VectorVectors(planes[4], planes[2], planes[0]);
15259         AnglesFromVectors(angles, localnormal, NULL, false);
15260         AngleVectors(angles, planes[0], planes[2], planes[4]);
15261         VectorNegate(planes[0], planes[1]);
15262         VectorNegate(planes[2], planes[3]);
15263         VectorNegate(planes[4], planes[5]);
15264         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
15265         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
15266         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
15267         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
15268         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
15269         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
15270
15271 #if 1
15272 // works
15273 {
15274         matrix4x4_t forwardprojection;
15275         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
15276         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
15277 }
15278 #else
15279 // broken
15280 {
15281         float projectionvector[4][3];
15282         VectorScale(planes[0], ilocalsize, projectionvector[0]);
15283         VectorScale(planes[2], ilocalsize, projectionvector[1]);
15284         VectorScale(planes[4], ilocalsize, projectionvector[2]);
15285         projectionvector[0][0] = planes[0][0] * ilocalsize;
15286         projectionvector[0][1] = planes[1][0] * ilocalsize;
15287         projectionvector[0][2] = planes[2][0] * ilocalsize;
15288         projectionvector[1][0] = planes[0][1] * ilocalsize;
15289         projectionvector[1][1] = planes[1][1] * ilocalsize;
15290         projectionvector[1][2] = planes[2][1] * ilocalsize;
15291         projectionvector[2][0] = planes[0][2] * ilocalsize;
15292         projectionvector[2][1] = planes[1][2] * ilocalsize;
15293         projectionvector[2][2] = planes[2][2] * ilocalsize;
15294         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
15295         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
15296         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
15297         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
15298 }
15299 #endif
15300
15301         dynamic = model->surfmesh.isanimated;
15302         numsurfacelist = model->nummodelsurfaces;
15303         surfacelist = model->sortedmodelsurfaces;
15304         surfaces = model->data_surfaces;
15305
15306         bih = NULL;
15307         bih_triangles_count = -1;
15308         if(!dynamic)
15309         {
15310                 if(model->render_bih.numleafs)
15311                         bih = &model->render_bih;
15312                 else if(model->collision_bih.numleafs)
15313                         bih = &model->collision_bih;
15314         }
15315         if(bih)
15316                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
15317         if(bih_triangles_count == 0)
15318                 return;
15319         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
15320                 return;
15321         if(bih_triangles_count > 0)
15322         {
15323                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
15324                 {
15325                         surfaceindex = bih_surfaces[triangleindex];
15326                         surface = surfaces + surfaceindex;
15327                         texture = surface->texture;
15328                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
15329                                 continue;
15330                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
15331                                 continue;
15332                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
15333                 }
15334         }
15335         else
15336         {
15337                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
15338                 {
15339                         surfaceindex = surfacelist[surfacelistindex];
15340                         surface = surfaces + surfaceindex;
15341                         // check cull box first because it rejects more than any other check
15342                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
15343                                 continue;
15344                         // skip transparent surfaces
15345                         texture = surface->texture;
15346                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
15347                                 continue;
15348                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
15349                                 continue;
15350                         numtriangles = surface->num_triangles;
15351                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
15352                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
15353                 }
15354         }
15355 }
15356
15357 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
15358 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)
15359 {
15360         int renderentityindex;
15361         float worldmins[3];
15362         float worldmaxs[3];
15363         entity_render_t *ent;
15364
15365         if (!cl_decals_newsystem.integer)
15366                 return;
15367
15368         worldmins[0] = worldorigin[0] - worldsize;
15369         worldmins[1] = worldorigin[1] - worldsize;
15370         worldmins[2] = worldorigin[2] - worldsize;
15371         worldmaxs[0] = worldorigin[0] + worldsize;
15372         worldmaxs[1] = worldorigin[1] + worldsize;
15373         worldmaxs[2] = worldorigin[2] + worldsize;
15374
15375         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
15376
15377         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
15378         {
15379                 ent = r_refdef.scene.entities[renderentityindex];
15380                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
15381                         continue;
15382
15383                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
15384         }
15385 }
15386
15387 typedef struct r_decalsystem_splatqueue_s
15388 {
15389         vec3_t worldorigin;
15390         vec3_t worldnormal;
15391         float color[4];
15392         float tcrange[4];
15393         float worldsize;
15394         int decalsequence;
15395 }
15396 r_decalsystem_splatqueue_t;
15397
15398 int r_decalsystem_numqueued = 0;
15399 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
15400
15401 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)
15402 {
15403         r_decalsystem_splatqueue_t *queue;
15404
15405         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
15406                 return;
15407
15408         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
15409         VectorCopy(worldorigin, queue->worldorigin);
15410         VectorCopy(worldnormal, queue->worldnormal);
15411         Vector4Set(queue->color, r, g, b, a);
15412         Vector4Set(queue->tcrange, s1, t1, s2, t2);
15413         queue->worldsize = worldsize;
15414         queue->decalsequence = cl.decalsequence++;
15415 }
15416
15417 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
15418 {
15419         int i;
15420         r_decalsystem_splatqueue_t *queue;
15421
15422         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
15423                 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);
15424         r_decalsystem_numqueued = 0;
15425 }
15426
15427 extern cvar_t cl_decals_max;
15428 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
15429 {
15430         int i;
15431         decalsystem_t *decalsystem = &ent->decalsystem;
15432         int numdecals;
15433         int killsequence;
15434         tridecal_t *decal;
15435         float frametime;
15436         float lifetime;
15437
15438         if (!decalsystem->numdecals)
15439                 return;
15440
15441         if (r_showsurfaces.integer)
15442                 return;
15443
15444         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
15445         {
15446                 R_DecalSystem_Reset(decalsystem);
15447                 return;
15448         }
15449
15450         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
15451         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
15452
15453         if (decalsystem->lastupdatetime)
15454                 frametime = (cl.time - decalsystem->lastupdatetime);
15455         else
15456                 frametime = 0;
15457         decalsystem->lastupdatetime = cl.time;
15458         decal = decalsystem->decals;
15459         numdecals = decalsystem->numdecals;
15460
15461         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
15462         {
15463                 if (decal->color4ub[0][3])
15464                 {
15465                         decal->lived += frametime;
15466                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
15467                         {
15468                                 memset(decal, 0, sizeof(*decal));
15469                                 if (decalsystem->freedecal > i)
15470                                         decalsystem->freedecal = i;
15471                         }
15472                 }
15473         }
15474         decal = decalsystem->decals;
15475         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
15476                 numdecals--;
15477
15478         // collapse the array by shuffling the tail decals into the gaps
15479         for (;;)
15480         {
15481                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
15482                         decalsystem->freedecal++;
15483                 if (decalsystem->freedecal == numdecals)
15484                         break;
15485                 decal[decalsystem->freedecal] = decal[--numdecals];
15486         }
15487
15488         decalsystem->numdecals = numdecals;
15489
15490         if (numdecals <= 0)
15491         {
15492                 // if there are no decals left, reset decalsystem
15493                 R_DecalSystem_Reset(decalsystem);
15494         }
15495 }
15496
15497 extern skinframe_t *decalskinframe;
15498 static void R_DrawModelDecals_Entity(entity_render_t *ent)
15499 {
15500         int i;
15501         decalsystem_t *decalsystem = &ent->decalsystem;
15502         int numdecals;
15503         tridecal_t *decal;
15504         float faderate;
15505         float alpha;
15506         float *v3f;
15507         float *c4f;
15508         float *t2f;
15509         const int *e;
15510         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
15511         int numtris = 0;
15512
15513         numdecals = decalsystem->numdecals;
15514         if (!numdecals)
15515                 return;
15516
15517         if (r_showsurfaces.integer)
15518                 return;
15519
15520         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
15521         {
15522                 R_DecalSystem_Reset(decalsystem);
15523                 return;
15524         }
15525
15526         // if the model is static it doesn't matter what value we give for
15527         // wantnormals and wanttangents, so this logic uses only rules applicable
15528         // to a model, knowing that they are meaningless otherwise
15529         if (ent == r_refdef.scene.worldentity)
15530                 RSurf_ActiveWorldEntity();
15531         else
15532                 RSurf_ActiveModelEntity(ent, false, false, false);
15533
15534         decalsystem->lastupdatetime = cl.time;
15535         decal = decalsystem->decals;
15536
15537         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
15538
15539         // update vertex positions for animated models
15540         v3f = decalsystem->vertex3f;
15541         c4f = decalsystem->color4f;
15542         t2f = decalsystem->texcoord2f;
15543         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
15544         {
15545                 if (!decal->color4ub[0][3])
15546                         continue;
15547
15548                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
15549                         continue;
15550
15551                 // update color values for fading decals
15552                 if (decal->lived >= cl_decals_time.value)
15553                 {
15554                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
15555                         alpha *= (1.0f/255.0f);
15556                 }
15557                 else
15558                         alpha = 1.0f/255.0f;
15559
15560                 c4f[ 0] = decal->color4ub[0][0] * alpha;
15561                 c4f[ 1] = decal->color4ub[0][1] * alpha;
15562                 c4f[ 2] = decal->color4ub[0][2] * alpha;
15563                 c4f[ 3] = 1;
15564                 c4f[ 4] = decal->color4ub[1][0] * alpha;
15565                 c4f[ 5] = decal->color4ub[1][1] * alpha;
15566                 c4f[ 6] = decal->color4ub[1][2] * alpha;
15567                 c4f[ 7] = 1;
15568                 c4f[ 8] = decal->color4ub[2][0] * alpha;
15569                 c4f[ 9] = decal->color4ub[2][1] * alpha;
15570                 c4f[10] = decal->color4ub[2][2] * alpha;
15571                 c4f[11] = 1;
15572
15573                 t2f[0] = decal->texcoord2f[0][0];
15574                 t2f[1] = decal->texcoord2f[0][1];
15575                 t2f[2] = decal->texcoord2f[1][0];
15576                 t2f[3] = decal->texcoord2f[1][1];
15577                 t2f[4] = decal->texcoord2f[2][0];
15578                 t2f[5] = decal->texcoord2f[2][1];
15579
15580                 // update vertex positions for animated models
15581                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
15582                 {
15583                         e = rsurface.modelelement3i + 3*decal->triangleindex;
15584                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
15585                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
15586                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
15587                 }
15588                 else
15589                 {
15590                         VectorCopy(decal->vertex3f[0], v3f);
15591                         VectorCopy(decal->vertex3f[1], v3f + 3);
15592                         VectorCopy(decal->vertex3f[2], v3f + 6);
15593                 }
15594
15595                 if (r_refdef.fogenabled)
15596                 {
15597                         alpha = RSurf_FogVertex(v3f);
15598                         VectorScale(c4f, alpha, c4f);
15599                         alpha = RSurf_FogVertex(v3f + 3);
15600                         VectorScale(c4f + 4, alpha, c4f + 4);
15601                         alpha = RSurf_FogVertex(v3f + 6);
15602                         VectorScale(c4f + 8, alpha, c4f + 8);
15603                 }
15604
15605                 v3f += 9;
15606                 c4f += 12;
15607                 t2f += 6;
15608                 numtris++;
15609         }
15610
15611         if (numtris > 0)
15612         {
15613                 r_refdef.stats.drawndecals += numtris;
15614
15615                 // now render the decals all at once
15616                 // (this assumes they all use one particle font texture!)
15617                 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);
15618 //              R_Mesh_ResetTextureState();
15619                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
15620                 GL_DepthMask(false);
15621                 GL_DepthRange(0, 1);
15622                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
15623                 GL_DepthTest(true);
15624                 GL_CullFace(GL_NONE);
15625                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
15626                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
15627                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
15628         }
15629 }
15630
15631 static void R_DrawModelDecals(void)
15632 {
15633         int i, numdecals;
15634
15635         // fade faster when there are too many decals
15636         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
15637         for (i = 0;i < r_refdef.scene.numentities;i++)
15638                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
15639
15640         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
15641         for (i = 0;i < r_refdef.scene.numentities;i++)
15642                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
15643                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
15644
15645         R_DecalSystem_ApplySplatEntitiesQueue();
15646
15647         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
15648         for (i = 0;i < r_refdef.scene.numentities;i++)
15649                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
15650
15651         r_refdef.stats.totaldecals += numdecals;
15652
15653         if (r_showsurfaces.integer)
15654                 return;
15655
15656         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
15657
15658         for (i = 0;i < r_refdef.scene.numentities;i++)
15659         {
15660                 if (!r_refdef.viewcache.entityvisible[i])
15661                         continue;
15662                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
15663                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
15664         }
15665 }
15666
15667 extern cvar_t mod_collision_bih;
15668 void R_DrawDebugModel(void)
15669 {
15670         entity_render_t *ent = rsurface.entity;
15671         int i, j, k, l, flagsmask;
15672         const msurface_t *surface;
15673         dp_model_t *model = ent->model;
15674         vec3_t v;
15675
15676         switch(vid.renderpath)
15677         {
15678         case RENDERPATH_GL11:
15679         case RENDERPATH_GL13:
15680         case RENDERPATH_GL20:
15681         case RENDERPATH_CGGL:
15682                 break;
15683         case RENDERPATH_D3D9:
15684                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
15685                 return;
15686         case RENDERPATH_D3D10:
15687                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
15688                 return;
15689         case RENDERPATH_D3D11:
15690                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
15691                 return;
15692         case RENDERPATH_SOFT:
15693                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
15694                 return;
15695         case RENDERPATH_GLES2:
15696                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
15697                 break;
15698         }
15699
15700         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
15701
15702 //      R_Mesh_ResetTextureState();
15703         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
15704         GL_DepthRange(0, 1);
15705         GL_DepthTest(!r_showdisabledepthtest.integer);
15706         GL_DepthMask(false);
15707         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
15708
15709         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
15710         {
15711                 int triangleindex;
15712                 int bihleafindex;
15713                 qboolean cullbox = ent == r_refdef.scene.worldentity;
15714                 const q3mbrush_t *brush;
15715                 const bih_t *bih = &model->collision_bih;
15716                 const bih_leaf_t *bihleaf;
15717                 float vertex3f[3][3];
15718                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
15719                 cullbox = false;
15720                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
15721                 {
15722                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
15723                                 continue;
15724                         switch (bihleaf->type)
15725                         {
15726                         case BIH_BRUSH:
15727                                 brush = model->brush.data_brushes + bihleaf->itemindex;
15728                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
15729                                 {
15730                                         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);
15731                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
15732                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
15733                                 }
15734                                 break;
15735                         case BIH_COLLISIONTRIANGLE:
15736                                 triangleindex = bihleaf->itemindex;
15737                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
15738                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
15739                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
15740                                 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);
15741                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
15742                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
15743                                 break;
15744                         case BIH_RENDERTRIANGLE:
15745                                 triangleindex = bihleaf->itemindex;
15746                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
15747                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
15748                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
15749                                 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);
15750                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
15751                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
15752                                 break;
15753                         }
15754                 }
15755         }
15756
15757         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
15758
15759         if (r_showtris.integer || (r_shownormals.value != 0))
15760         {
15761                 if (r_showdisabledepthtest.integer)
15762                 {
15763                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
15764                         GL_DepthMask(false);
15765                 }
15766                 else
15767                 {
15768                         GL_BlendFunc(GL_ONE, GL_ZERO);
15769                         GL_DepthMask(true);
15770                 }
15771                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
15772                 {
15773                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
15774                                 continue;
15775                         rsurface.texture = R_GetCurrentTexture(surface->texture);
15776                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
15777                         {
15778                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
15779                                 if (r_showtris.value > 0)
15780                                 {
15781                                         if (!rsurface.texture->currentlayers->depthmask)
15782                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
15783                                         else if (ent == r_refdef.scene.worldentity)
15784                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
15785                                         else
15786                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
15787                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
15788                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
15789                                         RSurf_DrawBatch();
15790                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
15791                                         CHECKGLERROR
15792                                 }
15793                                 if (r_shownormals.value < 0)
15794                                 {
15795                                         qglBegin(GL_LINES);
15796                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
15797                                         {
15798                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
15799                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
15800                                                 qglVertex3f(v[0], v[1], v[2]);
15801                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
15802                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
15803                                                 qglVertex3f(v[0], v[1], v[2]);
15804                                         }
15805                                         qglEnd();
15806                                         CHECKGLERROR
15807                                 }
15808                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
15809                                 {
15810                                         qglBegin(GL_LINES);
15811                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
15812                                         {
15813                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
15814                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
15815                                                 qglVertex3f(v[0], v[1], v[2]);
15816                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
15817                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
15818                                                 qglVertex3f(v[0], v[1], v[2]);
15819                                         }
15820                                         qglEnd();
15821                                         CHECKGLERROR
15822                                         qglBegin(GL_LINES);
15823                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
15824                                         {
15825                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
15826                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
15827                                                 qglVertex3f(v[0], v[1], v[2]);
15828                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
15829                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
15830                                                 qglVertex3f(v[0], v[1], v[2]);
15831                                         }
15832                                         qglEnd();
15833                                         CHECKGLERROR
15834                                         qglBegin(GL_LINES);
15835                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
15836                                         {
15837                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
15838                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
15839                                                 qglVertex3f(v[0], v[1], v[2]);
15840                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
15841                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
15842                                                 qglVertex3f(v[0], v[1], v[2]);
15843                                         }
15844                                         qglEnd();
15845                                         CHECKGLERROR
15846                                 }
15847                         }
15848                 }
15849                 rsurface.texture = NULL;
15850         }
15851 }
15852
15853 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
15854 int r_maxsurfacelist = 0;
15855 const msurface_t **r_surfacelist = NULL;
15856 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
15857 {
15858         int i, j, endj, flagsmask;
15859         dp_model_t *model = r_refdef.scene.worldmodel;
15860         msurface_t *surfaces;
15861         unsigned char *update;
15862         int numsurfacelist = 0;
15863         if (model == NULL)
15864                 return;
15865
15866         if (r_maxsurfacelist < model->num_surfaces)
15867         {
15868                 r_maxsurfacelist = model->num_surfaces;
15869                 if (r_surfacelist)
15870                         Mem_Free((msurface_t**)r_surfacelist);
15871                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
15872         }
15873
15874         RSurf_ActiveWorldEntity();
15875
15876         surfaces = model->data_surfaces;
15877         update = model->brushq1.lightmapupdateflags;
15878
15879         // update light styles on this submodel
15880         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
15881         {
15882                 model_brush_lightstyleinfo_t *style;
15883                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
15884                 {
15885                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
15886                         {
15887                                 int *list = style->surfacelist;
15888                                 style->value = r_refdef.scene.lightstylevalue[style->style];
15889                                 for (j = 0;j < style->numsurfaces;j++)
15890                                         update[list[j]] = true;
15891                         }
15892                 }
15893         }
15894
15895         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
15896
15897         if (debug)
15898         {
15899                 R_DrawDebugModel();
15900                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
15901                 return;
15902         }
15903
15904         rsurface.lightmaptexture = NULL;
15905         rsurface.deluxemaptexture = NULL;
15906         rsurface.uselightmaptexture = false;
15907         rsurface.texture = NULL;
15908         rsurface.rtlight = NULL;
15909         numsurfacelist = 0;
15910         // add visible surfaces to draw list
15911         for (i = 0;i < model->nummodelsurfaces;i++)
15912         {
15913                 j = model->sortedmodelsurfaces[i];
15914                 if (r_refdef.viewcache.world_surfacevisible[j])
15915                         r_surfacelist[numsurfacelist++] = surfaces + j;
15916         }
15917         // update lightmaps if needed
15918         if (model->brushq1.firstrender)
15919         {
15920                 model->brushq1.firstrender = false;
15921                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
15922                         if (update[j])
15923                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
15924         }
15925         else if (update)
15926         {
15927                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
15928                         if (r_refdef.viewcache.world_surfacevisible[j])
15929                                 if (update[j])
15930                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
15931         }
15932         // don't do anything if there were no surfaces
15933         if (!numsurfacelist)
15934         {
15935                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
15936                 return;
15937         }
15938         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
15939         GL_AlphaTest(false);
15940
15941         // add to stats if desired
15942         if (r_speeds.integer && !skysurfaces && !depthonly)
15943         {
15944                 r_refdef.stats.world_surfaces += numsurfacelist;
15945                 for (j = 0;j < numsurfacelist;j++)
15946                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
15947         }
15948
15949         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
15950 }
15951
15952 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
15953 {
15954         int i, j, endj, flagsmask;
15955         dp_model_t *model = ent->model;
15956         msurface_t *surfaces;
15957         unsigned char *update;
15958         int numsurfacelist = 0;
15959         if (model == NULL)
15960                 return;
15961
15962         if (r_maxsurfacelist < model->num_surfaces)
15963         {
15964                 r_maxsurfacelist = model->num_surfaces;
15965                 if (r_surfacelist)
15966                         Mem_Free((msurface_t **)r_surfacelist);
15967                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
15968         }
15969
15970         // if the model is static it doesn't matter what value we give for
15971         // wantnormals and wanttangents, so this logic uses only rules applicable
15972         // to a model, knowing that they are meaningless otherwise
15973         if (ent == r_refdef.scene.worldentity)
15974                 RSurf_ActiveWorldEntity();
15975         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
15976                 RSurf_ActiveModelEntity(ent, false, false, false);
15977         else if (prepass)
15978                 RSurf_ActiveModelEntity(ent, true, true, true);
15979         else if (depthonly)
15980         {
15981                 switch (vid.renderpath)
15982                 {
15983                 case RENDERPATH_GL20:
15984                 case RENDERPATH_CGGL:
15985                 case RENDERPATH_D3D9:
15986                 case RENDERPATH_D3D10:
15987                 case RENDERPATH_D3D11:
15988                 case RENDERPATH_SOFT:
15989                 case RENDERPATH_GLES2:
15990                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
15991                         break;
15992                 case RENDERPATH_GL13:
15993                 case RENDERPATH_GL11:
15994                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
15995                         break;
15996                 }
15997         }
15998         else
15999         {
16000                 switch (vid.renderpath)
16001                 {
16002                 case RENDERPATH_GL20:
16003                 case RENDERPATH_CGGL:
16004                 case RENDERPATH_D3D9:
16005                 case RENDERPATH_D3D10:
16006                 case RENDERPATH_D3D11:
16007                 case RENDERPATH_SOFT:
16008                 case RENDERPATH_GLES2:
16009                         RSurf_ActiveModelEntity(ent, true, true, false);
16010                         break;
16011                 case RENDERPATH_GL13:
16012                 case RENDERPATH_GL11:
16013                         RSurf_ActiveModelEntity(ent, true, false, false);
16014                         break;
16015                 }
16016         }
16017
16018         surfaces = model->data_surfaces;
16019         update = model->brushq1.lightmapupdateflags;
16020
16021         // update light styles
16022         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
16023         {
16024                 model_brush_lightstyleinfo_t *style;
16025                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
16026                 {
16027                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
16028                         {
16029                                 int *list = style->surfacelist;
16030                                 style->value = r_refdef.scene.lightstylevalue[style->style];
16031                                 for (j = 0;j < style->numsurfaces;j++)
16032                                         update[list[j]] = true;
16033                         }
16034                 }
16035         }
16036
16037         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
16038
16039         if (debug)
16040         {
16041                 R_DrawDebugModel();
16042                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
16043                 return;
16044         }
16045
16046         rsurface.lightmaptexture = NULL;
16047         rsurface.deluxemaptexture = NULL;
16048         rsurface.uselightmaptexture = false;
16049         rsurface.texture = NULL;
16050         rsurface.rtlight = NULL;
16051         numsurfacelist = 0;
16052         // add visible surfaces to draw list
16053         for (i = 0;i < model->nummodelsurfaces;i++)
16054                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
16055         // don't do anything if there were no surfaces
16056         if (!numsurfacelist)
16057         {
16058                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
16059                 return;
16060         }
16061         // update lightmaps if needed
16062         if (update)
16063         {
16064                 int updated = 0;
16065                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
16066                 {
16067                         if (update[j])
16068                         {
16069                                 updated++;
16070                                 R_BuildLightMap(ent, surfaces + j);
16071                         }
16072                 }
16073         }
16074         if (update)
16075                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
16076                         if (update[j])
16077                                 R_BuildLightMap(ent, surfaces + j);
16078         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
16079         GL_AlphaTest(false);
16080
16081         // add to stats if desired
16082         if (r_speeds.integer && !skysurfaces && !depthonly)
16083         {
16084                 r_refdef.stats.entities_surfaces += numsurfacelist;
16085                 for (j = 0;j < numsurfacelist;j++)
16086                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
16087         }
16088
16089         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
16090 }
16091
16092 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
16093 {
16094         static texture_t texture;
16095         static msurface_t surface;
16096         const msurface_t *surfacelist = &surface;
16097
16098         // fake enough texture and surface state to render this geometry
16099
16100         texture.update_lastrenderframe = -1; // regenerate this texture
16101         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
16102         texture.currentskinframe = skinframe;
16103         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
16104         texture.offsetmapping = OFFSETMAPPING_OFF;
16105         texture.offsetscale = 1;
16106         texture.specularscalemod = 1;
16107         texture.specularpowermod = 1;
16108
16109         surface.texture = &texture;
16110         surface.num_triangles = numtriangles;
16111         surface.num_firsttriangle = firsttriangle;
16112         surface.num_vertices = numvertices;
16113         surface.num_firstvertex = firstvertex;
16114
16115         // now render it
16116         rsurface.texture = R_GetCurrentTexture(surface.texture);
16117         rsurface.lightmaptexture = NULL;
16118         rsurface.deluxemaptexture = NULL;
16119         rsurface.uselightmaptexture = false;
16120         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
16121 }
16122
16123 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)
16124 {
16125         static msurface_t surface;
16126         const msurface_t *surfacelist = &surface;
16127
16128         // fake enough texture and surface state to render this geometry
16129         surface.texture = texture;
16130         surface.num_triangles = numtriangles;
16131         surface.num_firsttriangle = firsttriangle;
16132         surface.num_vertices = numvertices;
16133         surface.num_firstvertex = firstvertex;
16134
16135         // now render it
16136         rsurface.texture = R_GetCurrentTexture(surface.texture);
16137         rsurface.lightmaptexture = NULL;
16138         rsurface.deluxemaptexture = NULL;
16139         rsurface.uselightmaptexture = false;
16140         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
16141 }