]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
variables referring to cg in a way that is used by both CGGL and D3D9
[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 "// GL ES shaders use precision modifiers, standard GL does not\n"
595 "#ifndef GL_ES\n"
596 "#define lowp\n"
597 "#define mediump\n"
598 "#define highp\n"
599 "#endif\n"
600 "\n"
601 "#ifdef VERTEX_SHADER\n"
602 "attribute vec4 Attrib_Position;  // vertex\n"
603 "attribute vec4 Attrib_Color;     // color\n"
604 "attribute vec4 Attrib_TexCoord0; // material texcoords\n"
605 "attribute vec3 Attrib_TexCoord1; // svector\n"
606 "attribute vec3 Attrib_TexCoord2; // tvector\n"
607 "attribute vec3 Attrib_TexCoord3; // normal\n"
608 "attribute vec4 Attrib_TexCoord4; // lightmap texcoords\n"
609 "#endif\n"
610 "varying lowp vec4 VertexColor;\n"
611 "\n"
612 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
613 "# define USEFOG\n"
614 "#endif\n"
615 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
616 "#define USELIGHTMAP\n"
617 "#endif\n"
618 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
619 "#define USEEYEVECTOR\n"
620 "#endif\n"
621 "\n"
622 "#ifdef USESHADOWMAP2D\n"
623 "# ifdef GL_EXT_gpu_shader4\n"
624 "#   extension GL_EXT_gpu_shader4 : enable\n"
625 "# endif\n"
626 "# ifdef GL_ARB_texture_gather\n"
627 "#   extension GL_ARB_texture_gather : enable\n"
628 "# else\n"
629 "#   ifdef GL_AMD_texture_texture4\n"
630 "#     extension GL_AMD_texture_texture4 : enable\n"
631 "#   endif\n"
632 "# endif\n"
633 "#endif\n"
634 "\n"
635 "//#ifdef USESHADOWSAMPLER\n"
636 "//# extension GL_ARB_shadow : enable\n"
637 "//#endif\n"
638 "\n"
639 "//#ifdef __GLSL_CG_DATA_TYPES\n"
640 "//# define myhalf half\n"
641 "//# define myhalf2 half2\n"
642 "//# define myhalf3 half3\n"
643 "//# define myhalf4 half4\n"
644 "//#else\n"
645 "# define myhalf mediump float\n"
646 "# define myhalf2 mediump vec2\n"
647 "# define myhalf3 mediump vec3\n"
648 "# define myhalf4 mediump vec4\n"
649 "//#endif\n"
650 "\n"
651 "#ifdef VERTEX_SHADER\n"
652 "uniform highp mat4 ModelViewProjectionMatrix;\n"
653 "#endif\n"
654 "\n"
655 "#ifdef MODE_DEPTH_OR_SHADOW\n"
656 "#ifdef VERTEX_SHADER\n"
657 "void main(void)\n"
658 "{\n"
659 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
660 "}\n"
661 "#endif\n"
662 "#else // !MODE_DEPTH_ORSHADOW\n"
663 "\n"
664 "\n"
665 "\n"
666 "\n"
667 "#ifdef MODE_SHOWDEPTH\n"
668 "#ifdef VERTEX_SHADER\n"
669 "void main(void)\n"
670 "{\n"
671 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
672 "       VertexColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
673 "}\n"
674 "#endif\n"
675 "\n"
676 "#ifdef FRAGMENT_SHADER\n"
677 "void main(void)\n"
678 "{\n"
679 "       gl_FragColor = VertexColor;\n"
680 "}\n"
681 "#endif\n"
682 "#else // !MODE_SHOWDEPTH\n"
683 "\n"
684 "\n"
685 "\n"
686 "\n"
687 "#ifdef MODE_POSTPROCESS\n"
688 "varying mediump vec2 TexCoord1;\n"
689 "varying mediump vec2 TexCoord2;\n"
690 "\n"
691 "#ifdef VERTEX_SHADER\n"
692 "void main(void)\n"
693 "{\n"
694 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
695 "       TexCoord1 = Attrib_TexCoord0.xy;\n"
696 "#ifdef USEBLOOM\n"
697 "       TexCoord2 = Attrib_TexCoord4.xy;\n"
698 "#endif\n"
699 "}\n"
700 "#endif\n"
701 "\n"
702 "#ifdef FRAGMENT_SHADER\n"
703 "uniform sampler2D Texture_First;\n"
704 "#ifdef USEBLOOM\n"
705 "uniform sampler2D Texture_Second;\n"
706 "uniform lowp vec4 BloomColorSubtract;\n"
707 "#endif\n"
708 "#ifdef USEGAMMARAMPS\n"
709 "uniform sampler2D Texture_GammaRamps;\n"
710 "#endif\n"
711 "#ifdef USESATURATION\n"
712 "uniform lowp float Saturation;\n"
713 "#endif\n"
714 "#ifdef USEVIEWTINT\n"
715 "uniform lowp vec4 ViewTintColor;\n"
716 "#endif\n"
717 "//uncomment these if you want to use them:\n"
718 "uniform mediump vec4 UserVec1;\n"
719 "uniform mediump vec4 UserVec2;\n"
720 "// uniform mediump vec4 UserVec3;\n"
721 "// uniform mediump vec4 UserVec4;\n"
722 "// uniform highp float ClientTime;\n"
723 "uniform mediump vec2 PixelSize;\n"
724 "void main(void)\n"
725 "{\n"
726 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
727 "#ifdef USEBLOOM\n"
728 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
729 "#endif\n"
730 "#ifdef USEVIEWTINT\n"
731 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
732 "#endif\n"
733 "\n"
734 "#ifdef USEPOSTPROCESSING\n"
735 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
736 "// 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"
737 "       float sobel = 1.0;\n"
738 "       // vec2 ts = textureSize(Texture_First, 0);\n"
739 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
740 "       vec2 px = PixelSize;\n"
741 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
742 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
743 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
744 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
745 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
746 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
747 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
748 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
749 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
750 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
751 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
752 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
753 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
754 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
755 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
756 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
757 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
758 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
759 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
760 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
761 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
762 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
763 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
764 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
765 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
766 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
767 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
768 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
769 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
770 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
771 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
772 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
773 "#endif\n"
774 "\n"
775 "#ifdef USESATURATION\n"
776 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
777 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
778 "       // 'vampire sight' effect, wheres red is compensated\n"
779 "       #ifdef SATURATION_REDCOMPENSATE\n"
780 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
781 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
782 "               gl_FragColor.r += rboost;\n"
783 "       #else\n"
784 "               // normal desaturation\n"
785 "               //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
786 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
787 "       #endif\n"
788 "#endif\n"
789 "\n"
790 "#ifdef USEGAMMARAMPS\n"
791 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
792 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
793 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
794 "#endif\n"
795 "}\n"
796 "#endif\n"
797 "#else // !MODE_POSTPROCESS\n"
798 "\n"
799 "\n"
800 "\n"
801 "\n"
802 "#ifdef MODE_GENERIC\n"
803 "#ifdef USEDIFFUSE\n"
804 "varying mediump vec2 TexCoord1;\n"
805 "#endif\n"
806 "#ifdef USESPECULAR\n"
807 "varying mediump vec2 TexCoord2;\n"
808 "#endif\n"
809 "#ifdef VERTEX_SHADER\n"
810 "void main(void)\n"
811 "{\n"
812 "       VertexColor = Attrib_Color;\n"
813 "#ifdef USEDIFFUSE\n"
814 "       TexCoord1 = Attrib_TexCoord0.xy;\n"
815 "#endif\n"
816 "#ifdef USESPECULAR\n"
817 "       TexCoord2 = Attrib_TexCoord1.xy;\n"
818 "#endif\n"
819 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
820 "}\n"
821 "#endif\n"
822 "\n"
823 "#ifdef FRAGMENT_SHADER\n"
824 "#ifdef USEDIFFUSE\n"
825 "uniform sampler2D Texture_First;\n"
826 "#endif\n"
827 "#ifdef USESPECULAR\n"
828 "uniform sampler2D Texture_Second;\n"
829 "#endif\n"
830 "\n"
831 "void main(void)\n"
832 "{\n"
833 "#ifdef USEVIEWTINT\n"
834 "       gl_FragColor = VertexColor;\n"
835 "#else\n"
836 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
837 "#endif\n"
838 "#ifdef USEDIFFUSE\n"
839 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
840 "#endif\n"
841 "\n"
842 "#ifdef USESPECULAR\n"
843 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
844 "# ifdef USECOLORMAPPING\n"
845 "       gl_FragColor *= tex2;\n"
846 "# endif\n"
847 "# ifdef USEGLOW\n"
848 "       gl_FragColor += tex2;\n"
849 "# endif\n"
850 "# ifdef USEVERTEXTEXTUREBLEND\n"
851 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
852 "# endif\n"
853 "#endif\n"
854 "}\n"
855 "#endif\n"
856 "#else // !MODE_GENERIC\n"
857 "\n"
858 "\n"
859 "\n"
860 "\n"
861 "#ifdef MODE_BLOOMBLUR\n"
862 "varying mediump vec2 TexCoord;\n"
863 "#ifdef VERTEX_SHADER\n"
864 "void main(void)\n"
865 "{\n"
866 "       VertexColor = Attrib_Color;\n"
867 "       TexCoord = Attrib_TexCoord0.xy;\n"
868 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
869 "}\n"
870 "#endif\n"
871 "\n"
872 "#ifdef FRAGMENT_SHADER\n"
873 "uniform sampler2D Texture_First;\n"
874 "uniform mediump vec4 BloomBlur_Parameters;\n"
875 "\n"
876 "void main(void)\n"
877 "{\n"
878 "       int i;\n"
879 "       vec2 tc = TexCoord;\n"
880 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
881 "       tc += BloomBlur_Parameters.xy;\n"
882 "       for (i = 1;i < SAMPLES;i++)\n"
883 "       {\n"
884 "               color += texture2D(Texture_First, tc).rgb;\n"
885 "               tc += BloomBlur_Parameters.xy;\n"
886 "       }\n"
887 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
888 "}\n"
889 "#endif\n"
890 "#else // !MODE_BLOOMBLUR\n"
891 "#ifdef MODE_REFRACTION\n"
892 "varying mediump vec2 TexCoord;\n"
893 "varying highp vec4 ModelViewProjectionPosition;\n"
894 "uniform highp mat4 TexMatrix;\n"
895 "#ifdef VERTEX_SHADER\n"
896 "\n"
897 "void main(void)\n"
898 "{\n"
899 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
900 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
901 "       ModelViewProjectionPosition = gl_Position;\n"
902 "}\n"
903 "#endif\n"
904 "\n"
905 "#ifdef FRAGMENT_SHADER\n"
906 "uniform sampler2D Texture_Normal;\n"
907 "uniform sampler2D Texture_Refraction;\n"
908 "uniform sampler2D Texture_Reflection;\n"
909 "\n"
910 "uniform mediump vec4 DistortScaleRefractReflect;\n"
911 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
912 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
913 "uniform lowp vec4 RefractColor;\n"
914 "uniform lowp vec4 ReflectColor;\n"
915 "uniform mediump float ReflectFactor;\n"
916 "uniform mediump float ReflectOffset;\n"
917 "\n"
918 "void main(void)\n"
919 "{\n"
920 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
921 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
922 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
923 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
924 "       // FIXME temporary hack to detect the case that the reflection\n"
925 "       // gets blackened at edges due to leaving the area that contains actual\n"
926 "       // content.\n"
927 "       // Remove this 'ack once we have a better way to stop this thing from\n"
928 "       // 'appening.\n"
929 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
930 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
931 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
932 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
933 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
934 "       gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
935 "}\n"
936 "#endif\n"
937 "#else // !MODE_REFRACTION\n"
938 "\n"
939 "\n"
940 "\n"
941 "\n"
942 "#ifdef MODE_WATER\n"
943 "varying mediump vec2 TexCoord;\n"
944 "varying highp vec3 EyeVector;\n"
945 "varying highp vec4 ModelViewProjectionPosition;\n"
946 "#ifdef VERTEX_SHADER\n"
947 "uniform highp vec3 EyePosition;\n"
948 "uniform highp mat4 TexMatrix;\n"
949 "\n"
950 "void main(void)\n"
951 "{\n"
952 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
953 "       vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
954 "       EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
955 "       EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
956 "       EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
957 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
958 "       ModelViewProjectionPosition = gl_Position;\n"
959 "}\n"
960 "#endif\n"
961 "\n"
962 "#ifdef FRAGMENT_SHADER\n"
963 "uniform sampler2D Texture_Normal;\n"
964 "uniform sampler2D Texture_Refraction;\n"
965 "uniform sampler2D Texture_Reflection;\n"
966 "\n"
967 "uniform mediump vec4 DistortScaleRefractReflect;\n"
968 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
969 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
970 "uniform lowp vec4 RefractColor;\n"
971 "uniform lowp vec4 ReflectColor;\n"
972 "uniform mediump float ReflectFactor;\n"
973 "uniform mediump float ReflectOffset;\n"
974 "uniform highp float ClientTime;\n"
975 "#ifdef USENORMALMAPSCROLLBLEND\n"
976 "uniform highp vec2 NormalmapScrollBlend;\n"
977 "#endif\n"
978 "\n"
979 "void main(void)\n"
980 "{\n"
981 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
982 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
983 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
984 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
985 "       // slight water animation via 2 layer scrolling (todo: tweak)\n"
986 "       #ifdef USENORMALMAPSCROLLBLEND\n"
987 "               vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
988 "               normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
989 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
990 "       #else\n"
991 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
992 "       #endif\n"
993 "       // FIXME temporary hack to detect the case that the reflection\n"
994 "       // gets blackened at edges due to leaving the area that contains actual\n"
995 "       // content.\n"
996 "       // Remove this 'ack once we have a better way to stop this thing from\n"
997 "       // 'appening.\n"
998 "       float f  = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
999 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
1000 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
1001 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
1002 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1003 "       f  = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
1004 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
1005 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
1006 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
1007 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1008 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1009 "       gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
1010 "}\n"
1011 "#endif\n"
1012 "#else // !MODE_WATER\n"
1013 "\n"
1014 "\n"
1015 "\n"
1016 "\n"
1017 "// common definitions between vertex shader and fragment shader:\n"
1018 "\n"
1019 "varying mediump vec2 TexCoord;\n"
1020 "#ifdef USEVERTEXTEXTUREBLEND\n"
1021 "varying mediump vec2 TexCoord2;\n"
1022 "#endif\n"
1023 "#ifdef USELIGHTMAP\n"
1024 "varying mediump vec2 TexCoordLightmap;\n"
1025 "#endif\n"
1026 "\n"
1027 "#ifdef MODE_LIGHTSOURCE\n"
1028 "varying mediump vec3 CubeVector;\n"
1029 "#endif\n"
1030 "\n"
1031 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1032 "varying mediump vec3 LightVector;\n"
1033 "#endif\n"
1034 "\n"
1035 "#ifdef USEEYEVECTOR\n"
1036 "varying highp vec3 EyeVector;\n"
1037 "#endif\n"
1038 "#ifdef USEFOG\n"
1039 "varying highp vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1040 "#endif\n"
1041 "\n"
1042 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1043 "varying lowp vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1044 "varying lowp vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1045 "varying lowp vec3 VectorR; // direction of R texcoord (surface normal)\n"
1046 "#endif\n"
1047 "\n"
1048 "#ifdef USEREFLECTION\n"
1049 "varying highp vec4 ModelViewProjectionPosition;\n"
1050 "#endif\n"
1051 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1052 "uniform highp vec3 LightPosition;\n"
1053 "varying highp vec4 ModelViewPosition;\n"
1054 "#endif\n"
1055 "\n"
1056 "#ifdef MODE_LIGHTSOURCE\n"
1057 "uniform highp vec3 LightPosition;\n"
1058 "#endif\n"
1059 "uniform highp vec3 EyePosition;\n"
1060 "#ifdef MODE_LIGHTDIRECTION\n"
1061 "uniform highp vec3 LightDir;\n"
1062 "#endif\n"
1063 "uniform highp vec4 FogPlane;\n"
1064 "\n"
1065 "#ifdef USESHADOWMAPORTHO\n"
1066 "varying mediump vec3 ShadowMapTC;\n"
1067 "#endif\n"
1068 "\n"
1069 "\n"
1070 "\n"
1071 "\n"
1072 "\n"
1073 "// 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"
1074 "\n"
1075 "// fragment shader specific:\n"
1076 "#ifdef FRAGMENT_SHADER\n"
1077 "\n"
1078 "uniform sampler2D Texture_Normal;\n"
1079 "uniform sampler2D Texture_Color;\n"
1080 "uniform sampler2D Texture_Gloss;\n"
1081 "#ifdef USEGLOW\n"
1082 "uniform sampler2D Texture_Glow;\n"
1083 "#endif\n"
1084 "#ifdef USEVERTEXTEXTUREBLEND\n"
1085 "uniform sampler2D Texture_SecondaryNormal;\n"
1086 "uniform sampler2D Texture_SecondaryColor;\n"
1087 "uniform sampler2D Texture_SecondaryGloss;\n"
1088 "#ifdef USEGLOW\n"
1089 "uniform sampler2D Texture_SecondaryGlow;\n"
1090 "#endif\n"
1091 "#endif\n"
1092 "#ifdef USECOLORMAPPING\n"
1093 "uniform sampler2D Texture_Pants;\n"
1094 "uniform sampler2D Texture_Shirt;\n"
1095 "#endif\n"
1096 "#ifdef USEFOG\n"
1097 "#ifdef USEFOGHEIGHTTEXTURE\n"
1098 "uniform sampler2D Texture_FogHeightTexture;\n"
1099 "#endif\n"
1100 "uniform sampler2D Texture_FogMask;\n"
1101 "#endif\n"
1102 "#ifdef USELIGHTMAP\n"
1103 "uniform sampler2D Texture_Lightmap;\n"
1104 "#endif\n"
1105 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1106 "uniform sampler2D Texture_Deluxemap;\n"
1107 "#endif\n"
1108 "#ifdef USEREFLECTION\n"
1109 "uniform sampler2D Texture_Reflection;\n"
1110 "#endif\n"
1111 "\n"
1112 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1113 "uniform sampler2D Texture_ScreenDepth;\n"
1114 "uniform sampler2D Texture_ScreenNormalMap;\n"
1115 "#endif\n"
1116 "#ifdef USEDEFERREDLIGHTMAP\n"
1117 "uniform sampler2D Texture_ScreenDiffuse;\n"
1118 "uniform sampler2D Texture_ScreenSpecular;\n"
1119 "#endif\n"
1120 "\n"
1121 "uniform lowp vec3 Color_Pants;\n"
1122 "uniform lowp vec3 Color_Shirt;\n"
1123 "uniform lowp vec3 FogColor;\n"
1124 "\n"
1125 "#ifdef USEFOG\n"
1126 "uniform highp float FogRangeRecip;\n"
1127 "uniform highp float FogPlaneViewDist;\n"
1128 "uniform highp float FogHeightFade;\n"
1129 "vec3 FogVertex(vec3 surfacecolor)\n"
1130 "{\n"
1131 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1132 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1133 "       float fogfrac;\n"
1134 "#ifdef USEFOGHEIGHTTEXTURE\n"
1135 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1136 "       fogfrac = fogheightpixel.a;\n"
1137 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1138 "#else\n"
1139 "# ifdef USEFOGOUTSIDE\n"
1140 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1141 "# else\n"
1142 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1143 "# endif\n"
1144 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1145 "#endif\n"
1146 "}\n"
1147 "#endif\n"
1148 "\n"
1149 "#ifdef USEOFFSETMAPPING\n"
1150 "uniform mediump float OffsetMapping_Scale;\n"
1151 "vec2 OffsetMapping(vec2 TexCoord)\n"
1152 "{\n"
1153 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1154 "       // 14 sample relief mapping: linear search and then binary search\n"
1155 "       // this basically steps forward a small amount repeatedly until it finds\n"
1156 "       // itself inside solid, then jitters forward and back using decreasing\n"
1157 "       // amounts to find the impact\n"
1158 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1159 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1160 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1161 "       vec3 RT = vec3(TexCoord, 1);\n"
1162 "       OffsetVector *= 0.1;\n"
1163 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1164 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1165 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1166 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1167 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1168 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1169 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1170 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1171 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1172 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1173 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1174 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1175 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1176 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1177 "       return RT.xy;\n"
1178 "#else\n"
1179 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1180 "       // this basically moves forward the full distance, and then backs up based\n"
1181 "       // on height of samples\n"
1182 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1183 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1184 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1185 "       TexCoord += OffsetVector;\n"
1186 "       OffsetVector *= 0.5;\n"
1187 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1188 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1189 "       return TexCoord;\n"
1190 "#endif\n"
1191 "}\n"
1192 "#endif // USEOFFSETMAPPING\n"
1193 "\n"
1194 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1195 "uniform sampler2D Texture_Attenuation;\n"
1196 "uniform samplerCube Texture_Cube;\n"
1197 "#endif\n"
1198 "\n"
1199 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1200 "\n"
1201 "#ifdef USESHADOWMAP2D\n"
1202 "# ifdef USESHADOWSAMPLER\n"
1203 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1204 "# else\n"
1205 "uniform sampler2D Texture_ShadowMap2D;\n"
1206 "# endif\n"
1207 "#endif\n"
1208 "\n"
1209 "#ifdef USESHADOWMAPVSDCT\n"
1210 "uniform samplerCube Texture_CubeProjection;\n"
1211 "#endif\n"
1212 "\n"
1213 "#if defined(USESHADOWMAP2D)\n"
1214 "uniform mediump vec2 ShadowMap_TextureScale;\n"
1215 "uniform mediump vec4 ShadowMap_Parameters;\n"
1216 "#endif\n"
1217 "\n"
1218 "#if defined(USESHADOWMAP2D)\n"
1219 "# ifdef USESHADOWMAPORTHO\n"
1220 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1221 "# else\n"
1222 "#  ifdef USESHADOWMAPVSDCT\n"
1223 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1224 "{\n"
1225 "       vec3 adir = abs(dir);\n"
1226 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1227 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1228 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1229 "}\n"
1230 "#  else\n"
1231 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1232 "{\n"
1233 "       vec3 adir = abs(dir);\n"
1234 "       float ma = adir.z;\n"
1235 "       vec4 proj = vec4(dir, 2.5);\n"
1236 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1237 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1238 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1239 "       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"
1240 "}\n"
1241 "#  endif\n"
1242 "# endif\n"
1243 "#endif // defined(USESHADOWMAP2D)\n"
1244 "\n"
1245 "# ifdef USESHADOWMAP2D\n"
1246 "float ShadowMapCompare(vec3 dir)\n"
1247 "{\n"
1248 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1249 "       float f;\n"
1250 "\n"
1251 "#  ifdef USESHADOWSAMPLER\n"
1252 "#    ifdef USESHADOWMAPPCF\n"
1253 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1254 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1255 "       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"
1256 "#    else\n"
1257 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1258 "#    endif\n"
1259 "#  else\n"
1260 "#    ifdef USESHADOWMAPPCF\n"
1261 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1262 "#      ifdef GL_ARB_texture_gather\n"
1263 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1264 "#      else\n"
1265 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1266 "#      endif\n"
1267 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1268 "#      if USESHADOWMAPPCF > 1\n"
1269 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1270 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1271 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1272 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1273 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1274 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1275 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1276 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1277 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1278 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1279 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1280 "       locols.yz += group2.ab;\n"
1281 "       hicols.yz += group8.rg;\n"
1282 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1283 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1284 "                               mix(locols, hicols, offset.y);\n"
1285 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1286 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1287 "       f = dot(cols, vec4(1.0/25.0));\n"
1288 "#      else\n"
1289 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1290 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1291 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1292 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1293 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1294 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1295 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1296 "#      endif\n"
1297 "#     else\n"
1298 "#      ifdef GL_EXT_gpu_shader4\n"
1299 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1300 "#      else\n"
1301 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1302 "#      endif\n"
1303 "#      if USESHADOWMAPPCF > 1\n"
1304 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1305 "       center *= ShadowMap_TextureScale;\n"
1306 "       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"
1307 "       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"
1308 "       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"
1309 "       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"
1310 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1311 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1312 "#      else\n"
1313 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1314 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1315 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1316 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1317 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1318 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1319 "#      endif\n"
1320 "#     endif\n"
1321 "#    else\n"
1322 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1323 "#    endif\n"
1324 "#  endif\n"
1325 "#  ifdef USESHADOWMAPORTHO\n"
1326 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1327 "#  else\n"
1328 "       return f;\n"
1329 "#  endif\n"
1330 "}\n"
1331 "# endif\n"
1332 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1333 "#endif // FRAGMENT_SHADER\n"
1334 "\n"
1335 "\n"
1336 "\n"
1337 "\n"
1338 "#ifdef MODE_DEFERREDGEOMETRY\n"
1339 "#ifdef VERTEX_SHADER\n"
1340 "uniform highp mat4 TexMatrix;\n"
1341 "#ifdef USEVERTEXTEXTUREBLEND\n"
1342 "uniform highp mat4 BackgroundTexMatrix;\n"
1343 "#endif\n"
1344 "uniform highp mat4 ModelViewMatrix;\n"
1345 "void main(void)\n"
1346 "{\n"
1347 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1348 "#ifdef USEVERTEXTEXTUREBLEND\n"
1349 "       VertexColor = Attrib_Color;\n"
1350 "       TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1351 "#endif\n"
1352 "\n"
1353 "       // transform unnormalized eye direction into tangent space\n"
1354 "#ifdef USEOFFSETMAPPING\n"
1355 "       vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1356 "       EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1357 "       EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1358 "       EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1359 "#endif\n"
1360 "\n"
1361 "       VectorS = (ModelViewMatrix * vec4(Attrib_TexCoord1.xyz, 0)).xyz;\n"
1362 "       VectorT = (ModelViewMatrix * vec4(Attrib_TexCoord2.xyz, 0)).xyz;\n"
1363 "       VectorR = (ModelViewMatrix * vec4(Attrib_TexCoord3.xyz, 0)).xyz;\n"
1364 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1365 "}\n"
1366 "#endif // VERTEX_SHADER\n"
1367 "\n"
1368 "#ifdef FRAGMENT_SHADER\n"
1369 "void main(void)\n"
1370 "{\n"
1371 "#ifdef USEOFFSETMAPPING\n"
1372 "       // apply offsetmapping\n"
1373 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1374 "#define TexCoord TexCoordOffset\n"
1375 "#endif\n"
1376 "\n"
1377 "#ifdef USEALPHAKILL\n"
1378 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1379 "               discard;\n"
1380 "#endif\n"
1381 "\n"
1382 "#ifdef USEVERTEXTEXTUREBLEND\n"
1383 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1384 "       float terrainblend = clamp(float(VertexColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1385 "       //float terrainblend = min(float(VertexColor.a) * alpha * 2.0, float(1.0));\n"
1386 "       //float terrainblend = float(VertexColor.a) * alpha > 0.5;\n"
1387 "#endif\n"
1388 "\n"
1389 "#ifdef USEVERTEXTEXTUREBLEND\n"
1390 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1391 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1392 "#else\n"
1393 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1394 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1395 "#endif\n"
1396 "\n"
1397 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1398 "}\n"
1399 "#endif // FRAGMENT_SHADER\n"
1400 "#else // !MODE_DEFERREDGEOMETRY\n"
1401 "\n"
1402 "\n"
1403 "\n"
1404 "\n"
1405 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1406 "#ifdef VERTEX_SHADER\n"
1407 "uniform highp mat4 ModelViewMatrix;\n"
1408 "void main(void)\n"
1409 "{\n"
1410 "       ModelViewPosition = ModelViewMatrix * Attrib_Position;\n"
1411 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1412 "}\n"
1413 "#endif // VERTEX_SHADER\n"
1414 "\n"
1415 "#ifdef FRAGMENT_SHADER\n"
1416 "uniform highp mat4 ViewToLight;\n"
1417 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1418 "uniform highp vec2 ScreenToDepth;\n"
1419 "uniform myhalf3 DeferredColor_Ambient;\n"
1420 "uniform myhalf3 DeferredColor_Diffuse;\n"
1421 "#ifdef USESPECULAR\n"
1422 "uniform myhalf3 DeferredColor_Specular;\n"
1423 "uniform myhalf SpecularPower;\n"
1424 "#endif\n"
1425 "uniform myhalf2 PixelToScreenTexCoord;\n"
1426 "void main(void)\n"
1427 "{\n"
1428 "       // calculate viewspace pixel position\n"
1429 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1430 "       vec3 position;\n"
1431 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1432 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1433 "       // decode viewspace pixel normal\n"
1434 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1435 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1436 "       // surfacenormal = pixel normal in viewspace\n"
1437 "       // LightVector = pixel to light in viewspace\n"
1438 "       // CubeVector = position in lightspace\n"
1439 "       // eyevector = pixel to view in viewspace\n"
1440 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1441 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1442 "#ifdef USEDIFFUSE\n"
1443 "       // calculate diffuse shading\n"
1444 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1445 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1446 "#endif\n"
1447 "#ifdef USESPECULAR\n"
1448 "       // calculate directional shading\n"
1449 "       vec3 eyevector = position * -1.0;\n"
1450 "#  ifdef USEEXACTSPECULARMATH\n"
1451 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1452 "#  else\n"
1453 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1454 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1455 "#  endif\n"
1456 "#endif\n"
1457 "\n"
1458 "#if defined(USESHADOWMAP2D)\n"
1459 "       fade *= ShadowMapCompare(CubeVector);\n"
1460 "#endif\n"
1461 "\n"
1462 "#ifdef USEDIFFUSE\n"
1463 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1464 "#else\n"
1465 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1466 "#endif\n"
1467 "#ifdef USESPECULAR\n"
1468 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1469 "#else\n"
1470 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1471 "#endif\n"
1472 "\n"
1473 "# ifdef USECUBEFILTER\n"
1474 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1475 "       gl_FragData[0].rgb *= cubecolor;\n"
1476 "       gl_FragData[1].rgb *= cubecolor;\n"
1477 "# endif\n"
1478 "}\n"
1479 "#endif // FRAGMENT_SHADER\n"
1480 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1481 "\n"
1482 "\n"
1483 "\n"
1484 "\n"
1485 "#ifdef VERTEX_SHADER\n"
1486 "uniform highp mat4 TexMatrix;\n"
1487 "#ifdef USEVERTEXTEXTUREBLEND\n"
1488 "uniform highp mat4 BackgroundTexMatrix;\n"
1489 "#endif\n"
1490 "#ifdef MODE_LIGHTSOURCE\n"
1491 "uniform highp mat4 ModelToLight;\n"
1492 "#endif\n"
1493 "#ifdef USESHADOWMAPORTHO\n"
1494 "uniform highp mat4 ShadowMapMatrix;\n"
1495 "#endif\n"
1496 "void main(void)\n"
1497 "{\n"
1498 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1499 "       VertexColor = Attrib_Color;\n"
1500 "#endif\n"
1501 "       // copy the surface texcoord\n"
1502 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1503 "#ifdef USEVERTEXTEXTUREBLEND\n"
1504 "       TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1505 "#endif\n"
1506 "#ifdef USELIGHTMAP\n"
1507 "       TexCoordLightmap = vec2(Attrib_TexCoord4);\n"
1508 "#endif\n"
1509 "\n"
1510 "#ifdef MODE_LIGHTSOURCE\n"
1511 "       // transform vertex position into light attenuation/cubemap space\n"
1512 "       // (-1 to +1 across the light box)\n"
1513 "       CubeVector = vec3(ModelToLight * Attrib_Position);\n"
1514 "\n"
1515 "# ifdef USEDIFFUSE\n"
1516 "       // transform unnormalized light direction into tangent space\n"
1517 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1518 "       //  normalize it per pixel)\n"
1519 "       vec3 lightminusvertex = LightPosition - Attrib_Position.xyz;\n"
1520 "       LightVector.x = dot(lightminusvertex, Attrib_TexCoord1.xyz);\n"
1521 "       LightVector.y = dot(lightminusvertex, Attrib_TexCoord2.xyz);\n"
1522 "       LightVector.z = dot(lightminusvertex, Attrib_TexCoord3.xyz);\n"
1523 "# endif\n"
1524 "#endif\n"
1525 "\n"
1526 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1527 "       LightVector.x = dot(LightDir, Attrib_TexCoord1.xyz);\n"
1528 "       LightVector.y = dot(LightDir, Attrib_TexCoord2.xyz);\n"
1529 "       LightVector.z = dot(LightDir, Attrib_TexCoord3.xyz);\n"
1530 "#endif\n"
1531 "\n"
1532 "       // transform unnormalized eye direction into tangent space\n"
1533 "#ifdef USEEYEVECTOR\n"
1534 "       vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1535 "       EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1536 "       EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1537 "       EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1538 "#endif\n"
1539 "\n"
1540 "#ifdef USEFOG\n"
1541 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - Attrib_Position.xyz;\n"
1542 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, Attrib_Position);\n"
1543 "#endif\n"
1544 "\n"
1545 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1546 "       VectorS = Attrib_TexCoord1.xyz;\n"
1547 "       VectorT = Attrib_TexCoord2.xyz;\n"
1548 "       VectorR = Attrib_TexCoord3.xyz;\n"
1549 "#endif\n"
1550 "\n"
1551 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1552 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1553 "\n"
1554 "#ifdef USESHADOWMAPORTHO\n"
1555 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1556 "#endif\n"
1557 "\n"
1558 "#ifdef USEREFLECTION\n"
1559 "       ModelViewProjectionPosition = gl_Position;\n"
1560 "#endif\n"
1561 "}\n"
1562 "#endif // VERTEX_SHADER\n"
1563 "\n"
1564 "\n"
1565 "\n"
1566 "\n"
1567 "#ifdef FRAGMENT_SHADER\n"
1568 "#ifdef USEDEFERREDLIGHTMAP\n"
1569 "uniform myhalf2 PixelToScreenTexCoord;\n"
1570 "uniform myhalf3 DeferredMod_Diffuse;\n"
1571 "uniform myhalf3 DeferredMod_Specular;\n"
1572 "#endif\n"
1573 "uniform myhalf3 Color_Ambient;\n"
1574 "uniform myhalf3 Color_Diffuse;\n"
1575 "uniform myhalf3 Color_Specular;\n"
1576 "uniform myhalf SpecularPower;\n"
1577 "#ifdef USEGLOW\n"
1578 "uniform myhalf3 Color_Glow;\n"
1579 "#endif\n"
1580 "uniform myhalf Alpha;\n"
1581 "#ifdef USEREFLECTION\n"
1582 "uniform mediump vec4 DistortScaleRefractReflect;\n"
1583 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
1584 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
1585 "uniform lowp vec4 ReflectColor;\n"
1586 "#endif\n"
1587 "#ifdef USEREFLECTCUBE\n"
1588 "uniform highp mat4 ModelToReflectCube;\n"
1589 "uniform sampler2D Texture_ReflectMask;\n"
1590 "uniform samplerCube Texture_ReflectCube;\n"
1591 "#endif\n"
1592 "#ifdef MODE_LIGHTDIRECTION\n"
1593 "uniform myhalf3 LightColor;\n"
1594 "#endif\n"
1595 "#ifdef MODE_LIGHTSOURCE\n"
1596 "uniform myhalf3 LightColor;\n"
1597 "#endif\n"
1598 "void main(void)\n"
1599 "{\n"
1600 "#ifdef USEOFFSETMAPPING\n"
1601 "       // apply offsetmapping\n"
1602 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1603 "#define TexCoord TexCoordOffset\n"
1604 "#endif\n"
1605 "\n"
1606 "       // combine the diffuse textures (base, pants, shirt)\n"
1607 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1608 "#ifdef USEALPHAKILL\n"
1609 "       if (color.a < 0.5)\n"
1610 "               discard;\n"
1611 "#endif\n"
1612 "       color.a *= Alpha;\n"
1613 "#ifdef USECOLORMAPPING\n"
1614 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1615 "#endif\n"
1616 "#ifdef USEVERTEXTEXTUREBLEND\n"
1617 "       myhalf terrainblend = clamp(myhalf(VertexColor.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1618 "       //myhalf terrainblend = min(myhalf(VertexColor.a) * color.a * 2.0, myhalf(1.0));\n"
1619 "       //myhalf terrainblend = myhalf(VertexColor.a) * color.a > 0.5;\n"
1620 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1621 "       color.a = 1.0;\n"
1622 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1623 "#endif\n"
1624 "\n"
1625 "       // get the surface normal\n"
1626 "#ifdef USEVERTEXTEXTUREBLEND\n"
1627 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1628 "#else\n"
1629 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1630 "#endif\n"
1631 "\n"
1632 "       // get the material colors\n"
1633 "       myhalf3 diffusetex = color.rgb;\n"
1634 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1635 "# ifdef USEVERTEXTEXTUREBLEND\n"
1636 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1637 "# else\n"
1638 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1639 "# endif\n"
1640 "#endif\n"
1641 "\n"
1642 "#ifdef USEREFLECTCUBE\n"
1643 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1644 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1645 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1646 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1647 "#endif\n"
1648 "\n"
1649 "\n"
1650 "\n"
1651 "\n"
1652 "#ifdef MODE_LIGHTSOURCE\n"
1653 "       // light source\n"
1654 "#ifdef USEDIFFUSE\n"
1655 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1656 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1657 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1658 "#ifdef USESPECULAR\n"
1659 "#ifdef USEEXACTSPECULARMATH\n"
1660 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1661 "#else\n"
1662 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1663 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1664 "#endif\n"
1665 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1666 "#endif\n"
1667 "#else\n"
1668 "       color.rgb = diffusetex * Color_Ambient;\n"
1669 "#endif\n"
1670 "       color.rgb *= LightColor;\n"
1671 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1672 "#if defined(USESHADOWMAP2D)\n"
1673 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1674 "#endif\n"
1675 "# ifdef USECUBEFILTER\n"
1676 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1677 "# endif\n"
1678 "#endif // MODE_LIGHTSOURCE\n"
1679 "\n"
1680 "\n"
1681 "\n"
1682 "\n"
1683 "#ifdef MODE_LIGHTDIRECTION\n"
1684 "#define SHADING\n"
1685 "#ifdef USEDIFFUSE\n"
1686 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1687 "#endif\n"
1688 "#define lightcolor LightColor\n"
1689 "#endif // MODE_LIGHTDIRECTION\n"
1690 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1691 "#define SHADING\n"
1692 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1693 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1694 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1695 "       // convert modelspace light vector to tangentspace\n"
1696 "       myhalf3 lightnormal;\n"
1697 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1698 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1699 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1700 "       lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1701 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1702 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1703 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1704 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1705 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1706 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1707 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1708 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1709 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1710 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1711 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1712 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1713 "#define SHADING\n"
1714 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1715 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1716 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1717 "#endif\n"
1718 "\n"
1719 "\n"
1720 "\n"
1721 "\n"
1722 "#ifdef MODE_FAKELIGHT\n"
1723 "#define SHADING\n"
1724 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1725 "myhalf3 lightcolor = myhalf3(1.0);\n"
1726 "#endif // MODE_FAKELIGHT\n"
1727 "\n"
1728 "\n"
1729 "\n"
1730 "\n"
1731 "#ifdef MODE_LIGHTMAP\n"
1732 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1733 "#endif // MODE_LIGHTMAP\n"
1734 "#ifdef MODE_VERTEXCOLOR\n"
1735 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(VertexColor.rgb) * Color_Diffuse);\n"
1736 "#endif // MODE_VERTEXCOLOR\n"
1737 "#ifdef MODE_FLATCOLOR\n"
1738 "       color.rgb = diffusetex * Color_Ambient;\n"
1739 "#endif // MODE_FLATCOLOR\n"
1740 "\n"
1741 "\n"
1742 "\n"
1743 "\n"
1744 "#ifdef SHADING\n"
1745 "# ifdef USEDIFFUSE\n"
1746 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1747 "#  ifdef USESPECULAR\n"
1748 "#   ifdef USEEXACTSPECULARMATH\n"
1749 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1750 "#   else\n"
1751 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1752 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1753 "#   endif\n"
1754 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1755 "#  else\n"
1756 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1757 "#  endif\n"
1758 "# else\n"
1759 "       color.rgb = diffusetex * Color_Ambient;\n"
1760 "# endif\n"
1761 "#endif\n"
1762 "\n"
1763 "#ifdef USESHADOWMAPORTHO\n"
1764 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1765 "#endif\n"
1766 "\n"
1767 "#ifdef USEDEFERREDLIGHTMAP\n"
1768 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1769 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1770 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1771 "#endif\n"
1772 "\n"
1773 "#ifdef USEGLOW\n"
1774 "#ifdef USEVERTEXTEXTUREBLEND\n"
1775 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1776 "#else\n"
1777 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1778 "#endif\n"
1779 "#endif\n"
1780 "\n"
1781 "#ifdef USEFOG\n"
1782 "       color.rgb = FogVertex(color.rgb);\n"
1783 "#endif\n"
1784 "\n"
1785 "       // 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"
1786 "#ifdef USEREFLECTION\n"
1787 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1788 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1789 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1790 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1791 "       // FIXME temporary hack to detect the case that the reflection\n"
1792 "       // gets blackened at edges due to leaving the area that contains actual\n"
1793 "       // content.\n"
1794 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1795 "       // 'appening.\n"
1796 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1797 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1798 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1799 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1800 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1801 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1802 "#endif\n"
1803 "\n"
1804 "       gl_FragColor = vec4(color);\n"
1805 "}\n"
1806 "#endif // FRAGMENT_SHADER\n"
1807 "\n"
1808 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1809 "#endif // !MODE_DEFERREDGEOMETRY\n"
1810 "#endif // !MODE_WATER\n"
1811 "#endif // !MODE_REFRACTION\n"
1812 "#endif // !MODE_BLOOMBLUR\n"
1813 "#endif // !MODE_GENERIC\n"
1814 "#endif // !MODE_POSTPROCESS\n"
1815 "#endif // !MODE_SHOWDEPTH\n"
1816 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1817 ;
1818
1819 /*
1820 =========================================================================================================================================================
1821
1822
1823
1824 =========================================================================================================================================================
1825
1826
1827
1828 =========================================================================================================================================================
1829
1830
1831
1832 =========================================================================================================================================================
1833
1834
1835
1836 =========================================================================================================================================================
1837
1838
1839
1840 =========================================================================================================================================================
1841
1842
1843
1844 =========================================================================================================================================================
1845 */
1846
1847 const char *builtinhlslshaderstring =
1848 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1849 "// written by Forest 'LordHavoc' Hale\n"
1850 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1851 "\n"
1852 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1853 "#if defined(USEREFLECTION)\n"
1854 "#undef USESHADOWMAPORTHO\n"
1855 "#endif\n"
1856 "\n"
1857 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1858 "# define USEFOG\n"
1859 "#endif\n"
1860 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1861 "#define USELIGHTMAP\n"
1862 "#endif\n"
1863 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1864 "#define USEEYEVECTOR\n"
1865 "#endif\n"
1866 "\n"
1867 "#ifdef FRAGMENT_SHADER\n"
1868 "#ifdef HLSL\n"
1869 "//#undef USESHADOWMAPPCF\n"
1870 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1871 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1872 "#else\n"
1873 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1874 "#endif\n"
1875 "#endif\n"
1876 "\n"
1877 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1878 "#ifdef VERTEX_SHADER\n"
1879 "void main\n"
1880 "(\n"
1881 "float4 gl_Vertex : POSITION,\n"
1882 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1883 "out float4 gl_Position : POSITION,\n"
1884 "out float Depth : TEXCOORD0\n"
1885 ")\n"
1886 "{\n"
1887 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1888 "       Depth = gl_Position.z;\n"
1889 "}\n"
1890 "#endif\n"
1891 "\n"
1892 "#ifdef FRAGMENT_SHADER\n"
1893 "void main\n"
1894 "(\n"
1895 "float Depth : TEXCOORD0,\n"
1896 "out float4 gl_FragColor : COLOR\n"
1897 ")\n"
1898 "{\n"
1899 "//     float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1900 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1901 "       temp.yz -= floor(temp.yz);\n"
1902 "       gl_FragColor = temp;\n"
1903 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1904 "}\n"
1905 "#endif\n"
1906 "#else // !MODE_DEPTH_ORSHADOW\n"
1907 "\n"
1908 "\n"
1909 "\n"
1910 "\n"
1911 "#ifdef MODE_SHOWDEPTH\n"
1912 "#ifdef VERTEX_SHADER\n"
1913 "void main\n"
1914 "(\n"
1915 "float4 gl_Vertex : POSITION,\n"
1916 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1917 "out float4 gl_Position : POSITION,\n"
1918 "out float4 gl_FrontColor : COLOR0\n"
1919 ")\n"
1920 "{\n"
1921 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1922 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1923 "}\n"
1924 "#endif\n"
1925 "\n"
1926 "#ifdef FRAGMENT_SHADER\n"
1927 "void main\n"
1928 "(\n"
1929 "float4 gl_FrontColor : COLOR0,\n"
1930 "out float4 gl_FragColor : COLOR\n"
1931 ")\n"
1932 "{\n"
1933 "       gl_FragColor = gl_FrontColor;\n"
1934 "}\n"
1935 "#endif\n"
1936 "#else // !MODE_SHOWDEPTH\n"
1937 "\n"
1938 "\n"
1939 "\n"
1940 "\n"
1941 "#ifdef MODE_POSTPROCESS\n"
1942 "\n"
1943 "#ifdef VERTEX_SHADER\n"
1944 "void main\n"
1945 "(\n"
1946 "float4 gl_Vertex : POSITION,\n"
1947 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1948 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1949 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1950 "out float4 gl_Position : POSITION,\n"
1951 "out float2 TexCoord1 : TEXCOORD0,\n"
1952 "out float2 TexCoord2 : TEXCOORD1\n"
1953 ")\n"
1954 "{\n"
1955 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1956 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1957 "#ifdef USEBLOOM\n"
1958 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1959 "#endif\n"
1960 "}\n"
1961 "#endif\n"
1962 "\n"
1963 "#ifdef FRAGMENT_SHADER\n"
1964 "void main\n"
1965 "(\n"
1966 "float2 TexCoord1 : TEXCOORD0,\n"
1967 "float2 TexCoord2 : TEXCOORD1,\n"
1968 "uniform sampler Texture_First : register(s0),\n"
1969 "#ifdef USEBLOOM\n"
1970 "uniform sampler Texture_Second : register(s1),\n"
1971 "#endif\n"
1972 "#ifdef USEGAMMARAMPS\n"
1973 "uniform sampler Texture_GammaRamps : register(s2),\n"
1974 "#endif\n"
1975 "#ifdef USESATURATION\n"
1976 "uniform float Saturation : register(c30),\n"
1977 "#endif\n"
1978 "#ifdef USEVIEWTINT\n"
1979 "uniform float4 ViewTintColor : register(c41),\n"
1980 "#endif\n"
1981 "uniform float4 UserVec1 : register(c37),\n"
1982 "uniform float4 UserVec2 : register(c38),\n"
1983 "uniform float4 UserVec3 : register(c39),\n"
1984 "uniform float4 UserVec4 : register(c40),\n"
1985 "uniform float ClientTime : register(c2),\n"
1986 "uniform float2 PixelSize : register(c25),\n"
1987 "uniform float4 BloomColorSubtract : register(c43),\n"
1988 "out float4 gl_FragColor : COLOR\n"
1989 ")\n"
1990 "{\n"
1991 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1992 "#ifdef USEBLOOM\n"
1993 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1994 "#endif\n"
1995 "#ifdef USEVIEWTINT\n"
1996 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1997 "#endif\n"
1998 "\n"
1999 "#ifdef USEPOSTPROCESSING\n"
2000 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
2001 "// 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"
2002 "       float sobel = 1.0;\n"
2003 "       // float2 ts = textureSize(Texture_First, 0);\n"
2004 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
2005 "       float2 px = PixelSize;\n"
2006 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2007 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
2008 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2009 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2010 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
2011 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2012 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2013 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
2014 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2015 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2016 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
2017 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2018 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2019 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2020 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2021 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2022 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2023 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2024 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2025 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2026 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2027 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2028 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2029 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2030 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2031 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2032 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2033 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2034 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2035 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2036 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2037 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2038 "#endif\n"
2039 "\n"
2040 "#ifdef USESATURATION\n"
2041 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2042 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2043 "       // 'vampire sight' effect, wheres red is compensated\n"
2044 "       #ifdef SATURATION_REDCOMPENSATE\n"
2045 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2046 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2047 "               gl_FragColor.r += r;\n"
2048 "       #else\n"
2049 "               // normal desaturation\n"
2050 "               //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2051 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2052 "       #endif\n"
2053 "#endif\n"
2054 "\n"
2055 "#ifdef USEGAMMARAMPS\n"
2056 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2057 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2058 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2059 "#endif\n"
2060 "}\n"
2061 "#endif\n"
2062 "#else // !MODE_POSTPROCESS\n"
2063 "\n"
2064 "\n"
2065 "\n"
2066 "\n"
2067 "#ifdef MODE_GENERIC\n"
2068 "#ifdef VERTEX_SHADER\n"
2069 "void main\n"
2070 "(\n"
2071 "float4 gl_Vertex : POSITION,\n"
2072 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2073 "float4 gl_Color : COLOR0,\n"
2074 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2075 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2076 "out float4 gl_Position : POSITION,\n"
2077 "#ifdef USEDIFFUSE\n"
2078 "out float2 TexCoord1 : TEXCOORD0,\n"
2079 "#endif\n"
2080 "#ifdef USESPECULAR\n"
2081 "out float2 TexCoord2 : TEXCOORD1,\n"
2082 "#endif\n"
2083 "out float4 gl_FrontColor : COLOR\n"
2084 ")\n"
2085 "{\n"
2086 "#ifdef HLSL\n"
2087 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2088 "#else\n"
2089 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2090 "#endif\n"
2091 "#ifdef USEDIFFUSE\n"
2092 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2093 "#endif\n"
2094 "#ifdef USESPECULAR\n"
2095 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2096 "#endif\n"
2097 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2098 "}\n"
2099 "#endif\n"
2100 "\n"
2101 "#ifdef FRAGMENT_SHADER\n"
2102 "\n"
2103 "void main\n"
2104 "(\n"
2105 "float4 gl_FrontColor : COLOR0,\n"
2106 "float2 TexCoord1 : TEXCOORD0,\n"
2107 "float2 TexCoord2 : TEXCOORD1,\n"
2108 "#ifdef USEDIFFUSE\n"
2109 "uniform sampler Texture_First : register(s0),\n"
2110 "#endif\n"
2111 "#ifdef USESPECULAR\n"
2112 "uniform sampler Texture_Second : register(s1),\n"
2113 "#endif\n"
2114 "out float4 gl_FragColor : COLOR\n"
2115 ")\n"
2116 "{\n"
2117 "#ifdef USEVIEWTINT\n"
2118 "       gl_FragColor = gl_FrontColor;\n"
2119 "#else\n"
2120 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2121 "#endif\n"
2122 "#ifdef USEDIFFUSE\n"
2123 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2124 "#endif\n"
2125 "\n"
2126 "#ifdef USESPECULAR\n"
2127 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2128 "# ifdef USECOLORMAPPING\n"
2129 "       gl_FragColor *= tex2;\n"
2130 "# endif\n"
2131 "# ifdef USEGLOW\n"
2132 "       gl_FragColor += tex2;\n"
2133 "# endif\n"
2134 "# ifdef USEVERTEXTEXTUREBLEND\n"
2135 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2136 "# endif\n"
2137 "#endif\n"
2138 "}\n"
2139 "#endif\n"
2140 "#else // !MODE_GENERIC\n"
2141 "\n"
2142 "\n"
2143 "\n"
2144 "\n"
2145 "#ifdef MODE_BLOOMBLUR\n"
2146 "#ifdef VERTEX_SHADER\n"
2147 "void main\n"
2148 "(\n"
2149 "float4 gl_Vertex : POSITION,\n"
2150 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2151 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2152 "out float4 gl_Position : POSITION,\n"
2153 "out float2 TexCoord : TEXCOORD0\n"
2154 ")\n"
2155 "{\n"
2156 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2157 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2158 "}\n"
2159 "#endif\n"
2160 "\n"
2161 "#ifdef FRAGMENT_SHADER\n"
2162 "\n"
2163 "void main\n"
2164 "(\n"
2165 "float2 TexCoord : TEXCOORD0,\n"
2166 "uniform sampler Texture_First : register(s0),\n"
2167 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2168 "out float4 gl_FragColor : COLOR\n"
2169 ")\n"
2170 "{\n"
2171 "       int i;\n"
2172 "       float2 tc = TexCoord;\n"
2173 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2174 "       tc += BloomBlur_Parameters.xy;\n"
2175 "       for (i = 1;i < SAMPLES;i++)\n"
2176 "       {\n"
2177 "               color += tex2D(Texture_First, tc).rgb;\n"
2178 "               tc += BloomBlur_Parameters.xy;\n"
2179 "       }\n"
2180 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2181 "}\n"
2182 "#endif\n"
2183 "#else // !MODE_BLOOMBLUR\n"
2184 "#ifdef MODE_REFRACTION\n"
2185 "#ifdef VERTEX_SHADER\n"
2186 "void main\n"
2187 "(\n"
2188 "float4 gl_Vertex : POSITION,\n"
2189 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2190 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2191 "uniform float4x4 TexMatrix : register(c0),\n"
2192 "uniform float3 EyePosition : register(c24),\n"
2193 "out float4 gl_Position : POSITION,\n"
2194 "out float2 TexCoord : TEXCOORD0,\n"
2195 "out float3 EyeVector : TEXCOORD1,\n"
2196 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2197 ")\n"
2198 "{\n"
2199 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2200 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2201 "       ModelViewProjectionPosition = gl_Position;\n"
2202 "}\n"
2203 "#endif\n"
2204 "\n"
2205 "#ifdef FRAGMENT_SHADER\n"
2206 "void main\n"
2207 "(\n"
2208 "float2 TexCoord : TEXCOORD0,\n"
2209 "float3 EyeVector : TEXCOORD1,\n"
2210 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2211 "uniform sampler Texture_Normal : register(s0),\n"
2212 "uniform sampler Texture_Refraction : register(s3),\n"
2213 "uniform sampler Texture_Reflection : register(s7),\n"
2214 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2215 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2216 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2217 "uniform float4 RefractColor : register(c29),\n"
2218 "out float4 gl_FragColor : COLOR\n"
2219 ")\n"
2220 "{\n"
2221 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2222 "       //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"
2223 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2224 "       float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2225 "       // FIXME temporary hack to detect the case that the reflection\n"
2226 "       // gets blackened at edges due to leaving the area that contains actual\n"
2227 "       // content.\n"
2228 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2229 "       // 'appening.\n"
2230 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2231 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2232 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2233 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2234 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2235 "       gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2236 "}\n"
2237 "#endif\n"
2238 "#else // !MODE_REFRACTION\n"
2239 "\n"
2240 "\n"
2241 "\n"
2242 "\n"
2243 "#ifdef MODE_WATER\n"
2244 "#ifdef VERTEX_SHADER\n"
2245 "\n"
2246 "void main\n"
2247 "(\n"
2248 "float4 gl_Vertex : POSITION,\n"
2249 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2250 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2251 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2252 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2253 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2254 "uniform float4x4 TexMatrix : register(c0),\n"
2255 "uniform float3 EyePosition : register(c24),\n"
2256 "out float4 gl_Position : POSITION,\n"
2257 "out float2 TexCoord : TEXCOORD0,\n"
2258 "out float3 EyeVector : TEXCOORD1,\n"
2259 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2260 ")\n"
2261 "{\n"
2262 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2263 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2264 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2265 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2266 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2267 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2268 "       ModelViewProjectionPosition = gl_Position;\n"
2269 "}\n"
2270 "#endif\n"
2271 "\n"
2272 "#ifdef FRAGMENT_SHADER\n"
2273 "void main\n"
2274 "(\n"
2275 "float2 TexCoord : TEXCOORD0,\n"
2276 "float3 EyeVector : TEXCOORD1,\n"
2277 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2278 "uniform sampler Texture_Normal : register(s0),\n"
2279 "uniform sampler Texture_Refraction : register(s3),\n"
2280 "uniform sampler Texture_Reflection : register(s7),\n"
2281 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2282 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2283 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2284 "uniform float4 RefractColor : register(c29),\n"
2285 "uniform float4 ReflectColor : register(c26),\n"
2286 "uniform float ReflectFactor : register(c27),\n"
2287 "uniform float ReflectOffset : register(c28),\n"
2288 "out float4 gl_FragColor : COLOR\n"
2289 ")\n"
2290 "{\n"
2291 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2292 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2293 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2294 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2295 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2296 "       // FIXME temporary hack to detect the case that the reflection\n"
2297 "       // gets blackened at edges due to leaving the area that contains actual\n"
2298 "       // content.\n"
2299 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2300 "       // 'appening.\n"
2301 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2302 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2303 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2304 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2305 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2306 "       f  = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2307 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2308 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2309 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2310 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2311 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2312 "       gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2313 "}\n"
2314 "#endif\n"
2315 "#else // !MODE_WATER\n"
2316 "\n"
2317 "\n"
2318 "\n"
2319 "\n"
2320 "// 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"
2321 "\n"
2322 "// fragment shader specific:\n"
2323 "#ifdef FRAGMENT_SHADER\n"
2324 "\n"
2325 "#ifdef USEFOG\n"
2326 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2327 "{\n"
2328 "       float fogfrac;\n"
2329 "#ifdef USEFOGHEIGHTTEXTURE\n"
2330 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2331 "       fogfrac = fogheightpixel.a;\n"
2332 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2333 "#else\n"
2334 "# ifdef USEFOGOUTSIDE\n"
2335 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2336 "# else\n"
2337 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2338 "# endif\n"
2339 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2340 "#endif\n"
2341 "}\n"
2342 "#endif\n"
2343 "\n"
2344 "#ifdef USEOFFSETMAPPING\n"
2345 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2346 "{\n"
2347 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2348 "       // 14 sample relief mapping: linear search and then binary search\n"
2349 "       // this basically steps forward a small amount repeatedly until it finds\n"
2350 "       // itself inside solid, then jitters forward and back using decreasing\n"
2351 "       // amounts to find the impact\n"
2352 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2353 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2354 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2355 "       float3 RT = float3(TexCoord, 1);\n"
2356 "       OffsetVector *= 0.1;\n"
2357 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2358 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2359 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2360 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2361 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2362 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2363 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2364 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2365 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2366 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2367 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2368 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2369 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2370 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2371 "       return RT.xy;\n"
2372 "#else\n"
2373 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2374 "       // this basically moves forward the full distance, and then backs up based\n"
2375 "       // on height of samples\n"
2376 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2377 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2378 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2379 "       TexCoord += OffsetVector;\n"
2380 "       OffsetVector *= 0.333;\n"
2381 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2382 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2383 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2384 "       return TexCoord;\n"
2385 "#endif\n"
2386 "}\n"
2387 "#endif // USEOFFSETMAPPING\n"
2388 "\n"
2389 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2390 "#if defined(USESHADOWMAP2D)\n"
2391 "# ifdef USESHADOWMAPORTHO\n"
2392 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2393 "# else\n"
2394 "#  ifdef USESHADOWMAPVSDCT\n"
2395 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2396 "{\n"
2397 "       float3 adir = abs(dir);\n"
2398 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2399 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2400 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2401 "}\n"
2402 "#  else\n"
2403 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2404 "{\n"
2405 "       float3 adir = abs(dir);\n"
2406 "       float ma = adir.z;\n"
2407 "       float4 proj = float4(dir, 2.5);\n"
2408 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2409 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2410 "#ifdef HLSL\n"
2411 "       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"
2412 "#else\n"
2413 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2414 "       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"
2415 "#endif\n"
2416 "}\n"
2417 "#  endif\n"
2418 "# endif\n"
2419 "#endif // defined(USESHADOWMAP2D)\n"
2420 "\n"
2421 "# ifdef USESHADOWMAP2D\n"
2422 "#ifdef USESHADOWMAPVSDCT\n"
2423 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2424 "#else\n"
2425 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2426 "#endif\n"
2427 "{\n"
2428 "#ifdef USESHADOWMAPVSDCT\n"
2429 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2430 "#else\n"
2431 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2432 "#endif\n"
2433 "       float f;\n"
2434 "\n"
2435 "#  ifdef USESHADOWSAMPLER\n"
2436 "#    ifdef USESHADOWMAPPCF\n"
2437 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2438 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2439 "       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"
2440 "#    else\n"
2441 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2442 "#    endif\n"
2443 "#  else\n"
2444 "#    ifdef USESHADOWMAPPCF\n"
2445 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2446 "#      ifdef GL_ARB_texture_gather\n"
2447 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2448 "#      else\n"
2449 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2450 "#      endif\n"
2451 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2452 "#      if USESHADOWMAPPCF > 1\n"
2453 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2454 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2455 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2456 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2457 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2458 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2459 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2460 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2461 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2462 "       float4 locols = float4(group1.ab, group3.ab);\n"
2463 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2464 "       locols.yz += group2.ab;\n"
2465 "       hicols.yz += group8.rg;\n"
2466 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2467 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2468 "                               lerp(locols, hicols, offset.y);\n"
2469 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2470 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2471 "       f = dot(cols, float4(1.0/25.0));\n"
2472 "#      else\n"
2473 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2474 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2475 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2476 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2477 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2478 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2479 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2480 "#      endif\n"
2481 "#     else\n"
2482 "#      ifdef GL_EXT_gpu_shader4\n"
2483 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2484 "#      else\n"
2485 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2486 "#      endif\n"
2487 "#      if USESHADOWMAPPCF > 1\n"
2488 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2489 "       center *= ShadowMap_TextureScale;\n"
2490 "       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"
2491 "       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"
2492 "       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"
2493 "       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"
2494 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2495 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2496 "#      else\n"
2497 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2498 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2499 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2500 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2501 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2502 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2503 "#      endif\n"
2504 "#     endif\n"
2505 "#    else\n"
2506 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2507 "#    endif\n"
2508 "#  endif\n"
2509 "#  ifdef USESHADOWMAPORTHO\n"
2510 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2511 "#  else\n"
2512 "       return f;\n"
2513 "#  endif\n"
2514 "}\n"
2515 "# endif\n"
2516 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2517 "#endif // FRAGMENT_SHADER\n"
2518 "\n"
2519 "\n"
2520 "\n"
2521 "\n"
2522 "#ifdef MODE_DEFERREDGEOMETRY\n"
2523 "#ifdef VERTEX_SHADER\n"
2524 "void main\n"
2525 "(\n"
2526 "float4 gl_Vertex : POSITION,\n"
2527 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2528 "#ifdef USEVERTEXTEXTUREBLEND\n"
2529 "float4 gl_Color : COLOR0,\n"
2530 "#endif\n"
2531 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2532 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2533 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2534 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2535 "uniform float4x4 TexMatrix : register(c0),\n"
2536 "#ifdef USEVERTEXTEXTUREBLEND\n"
2537 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2538 "#endif\n"
2539 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2540 "#ifdef USEOFFSETMAPPING\n"
2541 "uniform float3 EyePosition : register(c24),\n"
2542 "#endif\n"
2543 "out float4 gl_Position : POSITION,\n"
2544 "#ifdef USEVERTEXTEXTUREBLEND\n"
2545 "out float4 gl_FrontColor : COLOR,\n"
2546 "#endif\n"
2547 "out float4 TexCoordBoth : TEXCOORD0,\n"
2548 "#ifdef USEOFFSETMAPPING\n"
2549 "out float3 EyeVector : TEXCOORD2,\n"
2550 "#endif\n"
2551 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2552 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2553 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2554 ")\n"
2555 "{\n"
2556 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2557 "#ifdef USEVERTEXTEXTUREBLEND\n"
2558 "#ifdef HLSL\n"
2559 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2560 "#else\n"
2561 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2562 "#endif\n"
2563 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2564 "#endif\n"
2565 "\n"
2566 "       // transform unnormalized eye direction into tangent space\n"
2567 "#ifdef USEOFFSETMAPPING\n"
2568 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2569 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2570 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2571 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2572 "#endif\n"
2573 "\n"
2574 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2575 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2576 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2577 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2578 "       VectorR.w = gl_Position.z;\n"
2579 "}\n"
2580 "#endif // VERTEX_SHADER\n"
2581 "\n"
2582 "#ifdef FRAGMENT_SHADER\n"
2583 "void main\n"
2584 "(\n"
2585 "float4 TexCoordBoth : TEXCOORD0,\n"
2586 "float3 EyeVector : TEXCOORD2,\n"
2587 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2588 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2589 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2590 "uniform sampler Texture_Normal : register(s0),\n"
2591 "#ifdef USEALPHAKILL\n"
2592 "uniform sampler Texture_Color : register(s1),\n"
2593 "#endif\n"
2594 "uniform sampler Texture_Gloss : register(s2),\n"
2595 "#ifdef USEVERTEXTEXTUREBLEND\n"
2596 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2597 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2598 "#endif\n"
2599 "#ifdef USEOFFSETMAPPING\n"
2600 "uniform float OffsetMapping_Scale : register(c24),\n"
2601 "#endif\n"
2602 "uniform half SpecularPower : register(c36),\n"
2603 "#ifdef HLSL\n"
2604 "out float4 gl_FragData0 : COLOR0,\n"
2605 "out float4 gl_FragData1 : COLOR1\n"
2606 "#else\n"
2607 "out float4 gl_FragColor : COLOR\n"
2608 "#endif\n"
2609 ")\n"
2610 "{\n"
2611 "       float2 TexCoord = TexCoordBoth.xy;\n"
2612 "#ifdef USEOFFSETMAPPING\n"
2613 "       // apply offsetmapping\n"
2614 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2615 "#define TexCoord TexCoordOffset\n"
2616 "#endif\n"
2617 "\n"
2618 "#ifdef USEALPHAKILL\n"
2619 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2620 "               discard;\n"
2621 "#endif\n"
2622 "\n"
2623 "#ifdef USEVERTEXTEXTUREBLEND\n"
2624 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2625 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2626 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2627 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2628 "#endif\n"
2629 "\n"
2630 "#ifdef USEVERTEXTEXTUREBLEND\n"
2631 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2632 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2633 "#else\n"
2634 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2635 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2636 "#endif\n"
2637 "\n"
2638 "#ifdef HLSL\n"
2639 "       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"
2640 "       float Depth = VectorR.w / 256.0;\n"
2641 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2642 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2643 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2644 "       gl_FragData1 = depthcolor;\n"
2645 "#else\n"
2646 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2647 "#endif\n"
2648 "}\n"
2649 "#endif // FRAGMENT_SHADER\n"
2650 "#else // !MODE_DEFERREDGEOMETRY\n"
2651 "\n"
2652 "\n"
2653 "\n"
2654 "\n"
2655 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2656 "#ifdef VERTEX_SHADER\n"
2657 "void main\n"
2658 "(\n"
2659 "float4 gl_Vertex : POSITION,\n"
2660 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2661 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2662 "out float4 gl_Position : POSITION,\n"
2663 "out float4 ModelViewPosition : TEXCOORD0\n"
2664 ")\n"
2665 "{\n"
2666 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2667 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2668 "}\n"
2669 "#endif // VERTEX_SHADER\n"
2670 "\n"
2671 "#ifdef FRAGMENT_SHADER\n"
2672 "void main\n"
2673 "(\n"
2674 "#ifdef HLSL\n"
2675 "float2 Pixel : VPOS,\n"
2676 "#else\n"
2677 "float2 Pixel : WPOS,\n"
2678 "#endif\n"
2679 "float4 ModelViewPosition : TEXCOORD0,\n"
2680 "uniform float4x4 ViewToLight : register(c44),\n"
2681 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2682 "uniform float3 LightPosition : register(c23),\n"
2683 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2684 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2685 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2686 "#ifdef USESPECULAR\n"
2687 "uniform half3 DeferredColor_Specular : register(c11),\n"
2688 "uniform half SpecularPower : register(c36),\n"
2689 "#endif\n"
2690 "uniform sampler Texture_Attenuation : register(s9),\n"
2691 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2692 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2693 "\n"
2694 "#ifdef USECUBEFILTER\n"
2695 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2696 "#endif\n"
2697 "\n"
2698 "#ifdef USESHADOWMAP2D\n"
2699 "# ifdef USESHADOWSAMPLER\n"
2700 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2701 "# else\n"
2702 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2703 "# endif\n"
2704 "#endif\n"
2705 "\n"
2706 "#ifdef USESHADOWMAPVSDCT\n"
2707 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2708 "#endif\n"
2709 "\n"
2710 "#if defined(USESHADOWMAP2D)\n"
2711 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2712 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2713 "#endif\n"
2714 "\n"
2715 "out float4 gl_FragData0 : COLOR0,\n"
2716 "out float4 gl_FragData1 : COLOR1\n"
2717 ")\n"
2718 "{\n"
2719 "       // calculate viewspace pixel position\n"
2720 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2721 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2722 "       float3 position;\n"
2723 "#ifdef HLSL\n"
2724 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2725 "#else\n"
2726 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2727 "#endif\n"
2728 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2729 "       // decode viewspace pixel normal\n"
2730 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2731 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2732 "       // surfacenormal = pixel normal in viewspace\n"
2733 "       // LightVector = pixel to light in viewspace\n"
2734 "       // CubeVector = position in lightspace\n"
2735 "       // eyevector = pixel to view in viewspace\n"
2736 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2737 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2738 "#ifdef USEDIFFUSE\n"
2739 "       // calculate diffuse shading\n"
2740 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2741 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2742 "#endif\n"
2743 "#ifdef USESPECULAR\n"
2744 "       // calculate directional shading\n"
2745 "       float3 eyevector = position * -1.0;\n"
2746 "#  ifdef USEEXACTSPECULARMATH\n"
2747 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2748 "#  else\n"
2749 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2750 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2751 "#  endif\n"
2752 "#endif\n"
2753 "\n"
2754 "#if defined(USESHADOWMAP2D)\n"
2755 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2756 "#ifdef USESHADOWMAPVSDCT\n"
2757 ", Texture_CubeProjection\n"
2758 "#endif\n"
2759 "       ));\n"
2760 "#endif\n"
2761 "\n"
2762 "#ifdef USEDIFFUSE\n"
2763 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2764 "#else\n"
2765 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2766 "#endif\n"
2767 "#ifdef USESPECULAR\n"
2768 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2769 "#else\n"
2770 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2771 "#endif\n"
2772 "\n"
2773 "# ifdef USECUBEFILTER\n"
2774 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2775 "       gl_FragData0.rgb *= cubecolor;\n"
2776 "       gl_FragData1.rgb *= cubecolor;\n"
2777 "# endif\n"
2778 "}\n"
2779 "#endif // FRAGMENT_SHADER\n"
2780 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2781 "\n"
2782 "\n"
2783 "\n"
2784 "\n"
2785 "#ifdef VERTEX_SHADER\n"
2786 "void main\n"
2787 "(\n"
2788 "float4 gl_Vertex : POSITION,\n"
2789 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2790 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2791 "float4 gl_Color : COLOR0,\n"
2792 "#endif\n"
2793 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2794 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2795 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2796 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2797 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2798 "\n"
2799 "uniform float3 EyePosition : register(c24),\n"
2800 "uniform float4x4 TexMatrix : register(c0),\n"
2801 "#ifdef USEVERTEXTEXTUREBLEND\n"
2802 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2803 "#endif\n"
2804 "#ifdef MODE_LIGHTSOURCE\n"
2805 "uniform float4x4 ModelToLight : register(c20),\n"
2806 "#endif\n"
2807 "#ifdef MODE_LIGHTSOURCE\n"
2808 "uniform float3 LightPosition : register(c27),\n"
2809 "#endif\n"
2810 "#ifdef MODE_LIGHTDIRECTION\n"
2811 "uniform float3 LightDir : register(c26),\n"
2812 "#endif\n"
2813 "uniform float4 FogPlane : register(c25),\n"
2814 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2815 "uniform float3 LightPosition : register(c27),\n"
2816 "#endif\n"
2817 "#ifdef USESHADOWMAPORTHO\n"
2818 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2819 "#endif\n"
2820 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2821 "out float4 gl_FrontColor : COLOR,\n"
2822 "#endif\n"
2823 "out float4 TexCoordBoth : TEXCOORD0,\n"
2824 "#ifdef USELIGHTMAP\n"
2825 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2826 "#endif\n"
2827 "#ifdef USEEYEVECTOR\n"
2828 "out float3 EyeVector : TEXCOORD2,\n"
2829 "#endif\n"
2830 "#ifdef USEREFLECTION\n"
2831 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2832 "#endif\n"
2833 "#ifdef USEFOG\n"
2834 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2835 "#endif\n"
2836 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2837 "out float3 LightVector : TEXCOORD1,\n"
2838 "#endif\n"
2839 "#ifdef MODE_LIGHTSOURCE\n"
2840 "out float3 CubeVector : TEXCOORD3,\n"
2841 "#endif\n"
2842 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2843 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2844 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2845 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2846 "#endif\n"
2847 "#ifdef USESHADOWMAPORTHO\n"
2848 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2849 "#endif\n"
2850 "out float4 gl_Position : POSITION\n"
2851 ")\n"
2852 "{\n"
2853 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2854 "#ifdef HLSL\n"
2855 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2856 "#else\n"
2857 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2858 "#endif\n"
2859 "#endif\n"
2860 "       // copy the surface texcoord\n"
2861 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2862 "#ifdef USEVERTEXTEXTUREBLEND\n"
2863 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2864 "#endif\n"
2865 "#ifdef USELIGHTMAP\n"
2866 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2867 "#endif\n"
2868 "\n"
2869 "#ifdef MODE_LIGHTSOURCE\n"
2870 "       // transform vertex position into light attenuation/cubemap space\n"
2871 "       // (-1 to +1 across the light box)\n"
2872 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2873 "\n"
2874 "# ifdef USEDIFFUSE\n"
2875 "       // transform unnormalized light direction into tangent space\n"
2876 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2877 "       //  normalize it per pixel)\n"
2878 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2879 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2880 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2881 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2882 "# endif\n"
2883 "#endif\n"
2884 "\n"
2885 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2886 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2887 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2888 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2889 "#endif\n"
2890 "\n"
2891 "       // transform unnormalized eye direction into tangent space\n"
2892 "#ifdef USEEYEVECTOR\n"
2893 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2894 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2895 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2896 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2897 "#endif\n"
2898 "\n"
2899 "#ifdef USEFOG\n"
2900 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2901 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2902 "#endif\n"
2903 "\n"
2904 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2905 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2906 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2907 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2908 "#endif\n"
2909 "\n"
2910 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2911 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2912 "\n"
2913 "#ifdef USESHADOWMAPORTHO\n"
2914 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2915 "#endif\n"
2916 "\n"
2917 "#ifdef USEREFLECTION\n"
2918 "       ModelViewProjectionPosition = gl_Position;\n"
2919 "#endif\n"
2920 "}\n"
2921 "#endif // VERTEX_SHADER\n"
2922 "\n"
2923 "\n"
2924 "\n"
2925 "\n"
2926 "#ifdef FRAGMENT_SHADER\n"
2927 "void main\n"
2928 "(\n"
2929 "#ifdef USEDEFERREDLIGHTMAP\n"
2930 "#ifdef HLSL\n"
2931 "float2 Pixel : VPOS,\n"
2932 "#else\n"
2933 "float2 Pixel : WPOS,\n"
2934 "#endif\n"
2935 "#endif\n"
2936 "float4 gl_FrontColor : COLOR,\n"
2937 "float4 TexCoordBoth : TEXCOORD0,\n"
2938 "#ifdef USELIGHTMAP\n"
2939 "float2 TexCoordLightmap : TEXCOORD1,\n"
2940 "#endif\n"
2941 "#ifdef USEEYEVECTOR\n"
2942 "float3 EyeVector : TEXCOORD2,\n"
2943 "#endif\n"
2944 "#ifdef USEREFLECTION\n"
2945 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2946 "#endif\n"
2947 "#ifdef USEFOG\n"
2948 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2949 "#endif\n"
2950 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2951 "float3 LightVector : TEXCOORD1,\n"
2952 "#endif\n"
2953 "#ifdef MODE_LIGHTSOURCE\n"
2954 "float3 CubeVector : TEXCOORD3,\n"
2955 "#endif\n"
2956 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2957 "float4 ModelViewPosition : TEXCOORD0,\n"
2958 "#endif\n"
2959 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2960 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2961 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2962 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2963 "#endif\n"
2964 "#ifdef USESHADOWMAPORTHO\n"
2965 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2966 "#endif\n"
2967 "\n"
2968 "uniform sampler Texture_Normal : register(s0),\n"
2969 "uniform sampler Texture_Color : register(s1),\n"
2970 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2971 "uniform sampler Texture_Gloss : register(s2),\n"
2972 "#endif\n"
2973 "#ifdef USEGLOW\n"
2974 "uniform sampler Texture_Glow : register(s3),\n"
2975 "#endif\n"
2976 "#ifdef USEVERTEXTEXTUREBLEND\n"
2977 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2978 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2979 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2980 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2981 "#endif\n"
2982 "#ifdef USEGLOW\n"
2983 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2984 "#endif\n"
2985 "#endif\n"
2986 "#ifdef USECOLORMAPPING\n"
2987 "uniform sampler Texture_Pants : register(s4),\n"
2988 "uniform sampler Texture_Shirt : register(s7),\n"
2989 "#endif\n"
2990 "#ifdef USEFOG\n"
2991 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2992 "uniform sampler Texture_FogMask : register(s8),\n"
2993 "#endif\n"
2994 "#ifdef USELIGHTMAP\n"
2995 "uniform sampler Texture_Lightmap : register(s9),\n"
2996 "#endif\n"
2997 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2998 "uniform sampler Texture_Deluxemap : register(s10),\n"
2999 "#endif\n"
3000 "#ifdef USEREFLECTION\n"
3001 "uniform sampler Texture_Reflection : register(s7),\n"
3002 "#endif\n"
3003 "\n"
3004 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3005 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3006 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3007 "#endif\n"
3008 "#ifdef USEDEFERREDLIGHTMAP\n"
3009 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3010 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3011 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
3012 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
3013 "#endif\n"
3014 "\n"
3015 "#ifdef USECOLORMAPPING\n"
3016 "uniform half3 Color_Pants : register(c7),\n"
3017 "uniform half3 Color_Shirt : register(c8),\n"
3018 "#endif\n"
3019 "#ifdef USEFOG\n"
3020 "uniform float3 FogColor : register(c16),\n"
3021 "uniform float FogRangeRecip : register(c20),\n"
3022 "uniform float FogPlaneViewDist : register(c19),\n"
3023 "uniform float FogHeightFade : register(c17),\n"
3024 "#endif\n"
3025 "\n"
3026 "#ifdef USEOFFSETMAPPING\n"
3027 "uniform float OffsetMapping_Scale : register(c24),\n"
3028 "#endif\n"
3029 "\n"
3030 "#ifdef USEDEFERREDLIGHTMAP\n"
3031 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3032 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3033 "uniform half3 DeferredMod_Specular : register(c13),\n"
3034 "#endif\n"
3035 "uniform half3 Color_Ambient : register(c3),\n"
3036 "uniform half3 Color_Diffuse : register(c4),\n"
3037 "uniform half3 Color_Specular : register(c5),\n"
3038 "uniform half SpecularPower : register(c36),\n"
3039 "#ifdef USEGLOW\n"
3040 "uniform half3 Color_Glow : register(c6),\n"
3041 "#endif\n"
3042 "uniform half Alpha : register(c0),\n"
3043 "#ifdef USEREFLECTION\n"
3044 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3045 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3046 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3047 "uniform half4 ReflectColor : register(c26),\n"
3048 "#endif\n"
3049 "#ifdef USEREFLECTCUBE\n"
3050 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3051 "uniform sampler Texture_ReflectMask : register(s5),\n"
3052 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3053 "#endif\n"
3054 "#ifdef MODE_LIGHTDIRECTION\n"
3055 "uniform half3 LightColor : register(c21),\n"
3056 "#endif\n"
3057 "#ifdef MODE_LIGHTSOURCE\n"
3058 "uniform half3 LightColor : register(c21),\n"
3059 "#endif\n"
3060 "\n"
3061 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3062 "uniform sampler Texture_Attenuation : register(s9),\n"
3063 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3064 "#endif\n"
3065 "\n"
3066 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3067 "\n"
3068 "#ifdef USESHADOWMAP2D\n"
3069 "# ifdef USESHADOWSAMPLER\n"
3070 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3071 "# else\n"
3072 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3073 "# endif\n"
3074 "#endif\n"
3075 "\n"
3076 "#ifdef USESHADOWMAPVSDCT\n"
3077 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3078 "#endif\n"
3079 "\n"
3080 "#if defined(USESHADOWMAP2D)\n"
3081 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3082 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3083 "#endif\n"
3084 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3085 "\n"
3086 "out float4 gl_FragColor : COLOR\n"
3087 ")\n"
3088 "{\n"
3089 "       float2 TexCoord = TexCoordBoth.xy;\n"
3090 "#ifdef USEVERTEXTEXTUREBLEND\n"
3091 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3092 "#endif\n"
3093 "#ifdef USEOFFSETMAPPING\n"
3094 "       // apply offsetmapping\n"
3095 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3096 "#define TexCoord TexCoordOffset\n"
3097 "#endif\n"
3098 "\n"
3099 "       // combine the diffuse textures (base, pants, shirt)\n"
3100 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3101 "#ifdef USEALPHAKILL\n"
3102 "       if (color.a < 0.5)\n"
3103 "               discard;\n"
3104 "#endif\n"
3105 "       color.a *= Alpha;\n"
3106 "#ifdef USECOLORMAPPING\n"
3107 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3108 "#endif\n"
3109 "#ifdef USEVERTEXTEXTUREBLEND\n"
3110 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3111 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3112 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3113 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3114 "       color.a = 1.0;\n"
3115 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3116 "#endif\n"
3117 "\n"
3118 "       // get the surface normal\n"
3119 "#ifdef USEVERTEXTEXTUREBLEND\n"
3120 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3121 "#else\n"
3122 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3123 "#endif\n"
3124 "\n"
3125 "       // get the material colors\n"
3126 "       half3 diffusetex = color.rgb;\n"
3127 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3128 "# ifdef USEVERTEXTEXTUREBLEND\n"
3129 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3130 "# else\n"
3131 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3132 "# endif\n"
3133 "#endif\n"
3134 "\n"
3135 "#ifdef USEREFLECTCUBE\n"
3136 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3137 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3138 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3139 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3140 "#endif\n"
3141 "\n"
3142 "\n"
3143 "\n"
3144 "\n"
3145 "#ifdef MODE_LIGHTSOURCE\n"
3146 "       // light source\n"
3147 "#ifdef USEDIFFUSE\n"
3148 "       half3 lightnormal = half3(normalize(LightVector));\n"
3149 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3150 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3151 "#ifdef USESPECULAR\n"
3152 "#ifdef USEEXACTSPECULARMATH\n"
3153 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3154 "#else\n"
3155 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3156 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3157 "#endif\n"
3158 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3159 "#endif\n"
3160 "#else\n"
3161 "       color.rgb = diffusetex * Color_Ambient;\n"
3162 "#endif\n"
3163 "       color.rgb *= LightColor;\n"
3164 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3165 "#if defined(USESHADOWMAP2D)\n"
3166 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3167 "#ifdef USESHADOWMAPVSDCT\n"
3168 ", Texture_CubeProjection\n"
3169 "#endif\n"
3170 "       ));\n"
3171 "\n"
3172 "#endif\n"
3173 "# ifdef USECUBEFILTER\n"
3174 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3175 "# endif\n"
3176 "\n"
3177 "#ifdef USESHADOWMAP2D\n"
3178 "#ifdef USESHADOWMAPVSDCT\n"
3179 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3180 "#else\n"
3181 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3182 "#endif\n"
3183 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3184 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3185 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3186 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3187 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3188 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3189 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3190 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3191 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3192 "//     color.r = half(shadowmaptc.z);\n"
3193 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3194 "//     color.r = half(shadowmaptc.z);\n"
3195 "//     color.r = 1;\n"
3196 "//     color.rgb = abs(CubeVector);\n"
3197 "#endif\n"
3198 "//     color.rgb = half3(1,1,1);\n"
3199 "#endif // MODE_LIGHTSOURCE\n"
3200 "\n"
3201 "\n"
3202 "\n"
3203 "\n"
3204 "#ifdef MODE_LIGHTDIRECTION\n"
3205 "#define SHADING\n"
3206 "#ifdef USEDIFFUSE\n"
3207 "       half3 lightnormal = half3(normalize(LightVector));\n"
3208 "#endif\n"
3209 "#define lightcolor LightColor\n"
3210 "#endif // MODE_LIGHTDIRECTION\n"
3211 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3212 "#define SHADING\n"
3213 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3214 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3215 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3216 "       // convert modelspace light vector to tangentspace\n"
3217 "       half3 lightnormal;\n"
3218 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3219 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3220 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3221 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3222 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3223 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3224 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3225 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3226 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3227 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3228 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3229 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3230 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3231 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3232 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3233 "#define SHADING\n"
3234 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3235 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3236 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3237 "#endif\n"
3238 "\n"
3239 "\n"
3240 "\n"
3241 "\n"
3242 "#ifdef MODE_FAKELIGHT\n"
3243 "#define SHADING\n"
3244 "half3 lightnormal = half3(normalize(EyeVector));\n"
3245 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3246 "#endif // MODE_FAKELIGHT\n"
3247 "\n"
3248 "\n"
3249 "\n"
3250 "\n"
3251 "#ifdef MODE_LIGHTMAP\n"
3252 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3253 "#endif // MODE_LIGHTMAP\n"
3254 "#ifdef MODE_VERTEXCOLOR\n"
3255 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3256 "#endif // MODE_VERTEXCOLOR\n"
3257 "#ifdef MODE_FLATCOLOR\n"
3258 "       color.rgb = diffusetex * Color_Ambient;\n"
3259 "#endif // MODE_FLATCOLOR\n"
3260 "\n"
3261 "\n"
3262 "\n"
3263 "\n"
3264 "#ifdef SHADING\n"
3265 "# ifdef USEDIFFUSE\n"
3266 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3267 "#  ifdef USESPECULAR\n"
3268 "#   ifdef USEEXACTSPECULARMATH\n"
3269 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3270 "#   else\n"
3271 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3272 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3273 "#   endif\n"
3274 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3275 "#  else\n"
3276 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3277 "#  endif\n"
3278 "# else\n"
3279 "       color.rgb = diffusetex * Color_Ambient;\n"
3280 "# endif\n"
3281 "#endif\n"
3282 "\n"
3283 "#ifdef USESHADOWMAPORTHO\n"
3284 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3285 "#endif\n"
3286 "\n"
3287 "#ifdef USEDEFERREDLIGHTMAP\n"
3288 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3289 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3290 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3291 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3292 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3293 "#endif\n"
3294 "\n"
3295 "#ifdef USEGLOW\n"
3296 "#ifdef USEVERTEXTEXTUREBLEND\n"
3297 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3298 "#else\n"
3299 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3300 "#endif\n"
3301 "#endif\n"
3302 "\n"
3303 "#ifdef USEFOG\n"
3304 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3305 "#endif\n"
3306 "\n"
3307 "       // 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"
3308 "#ifdef USEREFLECTION\n"
3309 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3310 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3311 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3312 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3313 "       // FIXME temporary hack to detect the case that the reflection\n"
3314 "       // gets blackened at edges due to leaving the area that contains actual\n"
3315 "       // content.\n"
3316 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3317 "       // 'appening.\n"
3318 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3319 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3320 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3321 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3322 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3323 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3324 "#endif\n"
3325 "\n"
3326 "       gl_FragColor = float4(color);\n"
3327 "}\n"
3328 "#endif // FRAGMENT_SHADER\n"
3329 "\n"
3330 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3331 "#endif // !MODE_DEFERREDGEOMETRY\n"
3332 "#endif // !MODE_WATER\n"
3333 "#endif // !MODE_REFRACTION\n"
3334 "#endif // !MODE_BLOOMBLUR\n"
3335 "#endif // !MODE_GENERIC\n"
3336 "#endif // !MODE_POSTPROCESS\n"
3337 "#endif // !MODE_SHOWDEPTH\n"
3338 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3339 ;
3340
3341 char *glslshaderstring = NULL;
3342 char *hlslshaderstring = NULL;
3343
3344 //=======================================================================================================================================================
3345
3346 typedef struct shaderpermutationinfo_s
3347 {
3348         const char *pretext;
3349         const char *name;
3350 }
3351 shaderpermutationinfo_t;
3352
3353 typedef struct shadermodeinfo_s
3354 {
3355         const char *vertexfilename;
3356         const char *geometryfilename;
3357         const char *fragmentfilename;
3358         const char *pretext;
3359         const char *name;
3360 }
3361 shadermodeinfo_t;
3362
3363 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3364 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3365 {
3366         {"#define USEDIFFUSE\n", " diffuse"},
3367         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3368         {"#define USEVIEWTINT\n", " viewtint"},
3369         {"#define USECOLORMAPPING\n", " colormapping"},
3370         {"#define USESATURATION\n", " saturation"},
3371         {"#define USEFOGINSIDE\n", " foginside"},
3372         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3373         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3374         {"#define USEGAMMARAMPS\n", " gammaramps"},
3375         {"#define USECUBEFILTER\n", " cubefilter"},
3376         {"#define USEGLOW\n", " glow"},
3377         {"#define USEBLOOM\n", " bloom"},
3378         {"#define USESPECULAR\n", " specular"},
3379         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3380         {"#define USEREFLECTION\n", " reflection"},
3381         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3382         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3383         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3384         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3385         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3386         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3387         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3388         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3389         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3390         {"#define USEALPHAKILL\n", " alphakill"},
3391         {"#define USEREFLECTCUBE\n", " reflectcube"},
3392         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3393 };
3394
3395 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3396 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3397 {
3398         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3399         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3400         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3401         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3402         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3403         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3404         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3405         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3406         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3407         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3408         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3409         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3410         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3411         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3412         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3413         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3414 };
3415
3416 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3417 {
3418         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3419         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3420         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3421         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3422         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3423         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3424         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3425         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3426         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3427         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3428         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3429         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3430         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3431         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3432         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3433         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3434 };
3435
3436 struct r_glsl_permutation_s;
3437 typedef struct r_glsl_permutation_s
3438 {
3439         /// hash lookup data
3440         struct r_glsl_permutation_s *hashnext;
3441         unsigned int mode;
3442         unsigned int permutation;
3443
3444         /// indicates if we have tried compiling this permutation already
3445         qboolean compiled;
3446         /// 0 if compilation failed
3447         int program;
3448         // texture units assigned to each detected uniform
3449         int tex_Texture_First;
3450         int tex_Texture_Second;
3451         int tex_Texture_GammaRamps;
3452         int tex_Texture_Normal;
3453         int tex_Texture_Color;
3454         int tex_Texture_Gloss;
3455         int tex_Texture_Glow;
3456         int tex_Texture_SecondaryNormal;
3457         int tex_Texture_SecondaryColor;
3458         int tex_Texture_SecondaryGloss;
3459         int tex_Texture_SecondaryGlow;
3460         int tex_Texture_Pants;
3461         int tex_Texture_Shirt;
3462         int tex_Texture_FogHeightTexture;
3463         int tex_Texture_FogMask;
3464         int tex_Texture_Lightmap;
3465         int tex_Texture_Deluxemap;
3466         int tex_Texture_Attenuation;
3467         int tex_Texture_Cube;
3468         int tex_Texture_Refraction;
3469         int tex_Texture_Reflection;
3470         int tex_Texture_ShadowMap2D;
3471         int tex_Texture_CubeProjection;
3472         int tex_Texture_ScreenDepth;
3473         int tex_Texture_ScreenNormalMap;
3474         int tex_Texture_ScreenDiffuse;
3475         int tex_Texture_ScreenSpecular;
3476         int tex_Texture_ReflectMask;
3477         int tex_Texture_ReflectCube;
3478         /// locations of detected uniforms in program object, or -1 if not found
3479         int loc_Texture_First;
3480         int loc_Texture_Second;
3481         int loc_Texture_GammaRamps;
3482         int loc_Texture_Normal;
3483         int loc_Texture_Color;
3484         int loc_Texture_Gloss;
3485         int loc_Texture_Glow;
3486         int loc_Texture_SecondaryNormal;
3487         int loc_Texture_SecondaryColor;
3488         int loc_Texture_SecondaryGloss;
3489         int loc_Texture_SecondaryGlow;
3490         int loc_Texture_Pants;
3491         int loc_Texture_Shirt;
3492         int loc_Texture_FogHeightTexture;
3493         int loc_Texture_FogMask;
3494         int loc_Texture_Lightmap;
3495         int loc_Texture_Deluxemap;
3496         int loc_Texture_Attenuation;
3497         int loc_Texture_Cube;
3498         int loc_Texture_Refraction;
3499         int loc_Texture_Reflection;
3500         int loc_Texture_ShadowMap2D;
3501         int loc_Texture_CubeProjection;
3502         int loc_Texture_ScreenDepth;
3503         int loc_Texture_ScreenNormalMap;
3504         int loc_Texture_ScreenDiffuse;
3505         int loc_Texture_ScreenSpecular;
3506         int loc_Texture_ReflectMask;
3507         int loc_Texture_ReflectCube;
3508         int loc_Alpha;
3509         int loc_BloomBlur_Parameters;
3510         int loc_ClientTime;
3511         int loc_Color_Ambient;
3512         int loc_Color_Diffuse;
3513         int loc_Color_Specular;
3514         int loc_Color_Glow;
3515         int loc_Color_Pants;
3516         int loc_Color_Shirt;
3517         int loc_DeferredColor_Ambient;
3518         int loc_DeferredColor_Diffuse;
3519         int loc_DeferredColor_Specular;
3520         int loc_DeferredMod_Diffuse;
3521         int loc_DeferredMod_Specular;
3522         int loc_DistortScaleRefractReflect;
3523         int loc_EyePosition;
3524         int loc_FogColor;
3525         int loc_FogHeightFade;
3526         int loc_FogPlane;
3527         int loc_FogPlaneViewDist;
3528         int loc_FogRangeRecip;
3529         int loc_LightColor;
3530         int loc_LightDir;
3531         int loc_LightPosition;
3532         int loc_OffsetMapping_Scale;
3533         int loc_PixelSize;
3534         int loc_ReflectColor;
3535         int loc_ReflectFactor;
3536         int loc_ReflectOffset;
3537         int loc_RefractColor;
3538         int loc_Saturation;
3539         int loc_ScreenCenterRefractReflect;
3540         int loc_ScreenScaleRefractReflect;
3541         int loc_ScreenToDepth;
3542         int loc_ShadowMap_Parameters;
3543         int loc_ShadowMap_TextureScale;
3544         int loc_SpecularPower;
3545         int loc_UserVec1;
3546         int loc_UserVec2;
3547         int loc_UserVec3;
3548         int loc_UserVec4;
3549         int loc_ViewTintColor;
3550         int loc_ViewToLight;
3551         int loc_ModelToLight;
3552         int loc_TexMatrix;
3553         int loc_BackgroundTexMatrix;
3554         int loc_ModelViewProjectionMatrix;
3555         int loc_ModelViewMatrix;
3556         int loc_PixelToScreenTexCoord;
3557         int loc_ModelToReflectCube;
3558         int loc_ShadowMapMatrix;
3559         int loc_BloomColorSubtract;
3560         int loc_NormalmapScrollBlend;
3561 }
3562 r_glsl_permutation_t;
3563
3564 #define SHADERPERMUTATION_HASHSIZE 256
3565
3566
3567 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3568 // these can NOT degrade! only use for simple stuff
3569 enum
3570 {
3571         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3572         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3573         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3574         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3575         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3576         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
3577 };
3578 #define SHADERSTATICPARMS_COUNT 6
3579
3580 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3581 static int shaderstaticparms_count = 0;
3582
3583 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3584 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3585 qboolean R_CompileShader_CheckStaticParms(void)
3586 {
3587         static int r_compileshader_staticparms_save[1];
3588         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3589         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3590
3591         // detect all
3592         if (r_glsl_saturation_redcompensate.integer)
3593                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3594         if (r_shadow_glossexact.integer)
3595                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3596         if (r_glsl_postprocess.integer)
3597         {
3598                 if (r_glsl_postprocess_uservec1_enable.integer)
3599                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3600                 if (r_glsl_postprocess_uservec2_enable.integer)
3601                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3602                 if (r_glsl_postprocess_uservec3_enable.integer)
3603                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3604                 if (r_glsl_postprocess_uservec4_enable.integer)
3605                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3606         }
3607         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3608 }
3609
3610 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3611         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3612                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3613         else \
3614                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3615 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3616 {
3617         shaderstaticparms_count = 0;
3618
3619         // emit all
3620         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3621         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3622         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3623         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3624         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3625         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3626 }
3627
3628 /// information about each possible shader permutation
3629 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3630 /// currently selected permutation
3631 r_glsl_permutation_t *r_glsl_permutation;
3632 /// storage for permutations linked in the hash table
3633 memexpandablearray_t r_glsl_permutationarray;
3634
3635 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3636 {
3637         //unsigned int hashdepth = 0;
3638         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3639         r_glsl_permutation_t *p;
3640         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3641         {
3642                 if (p->mode == mode && p->permutation == permutation)
3643                 {
3644                         //if (hashdepth > 10)
3645                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3646                         return p;
3647                 }
3648                 //hashdepth++;
3649         }
3650         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3651         p->mode = mode;
3652         p->permutation = permutation;
3653         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3654         r_glsl_permutationhash[mode][hashindex] = p;
3655         //if (hashdepth > 10)
3656         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3657         return p;
3658 }
3659
3660 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3661 {
3662         char *shaderstring;
3663         if (!filename || !filename[0])
3664                 return NULL;
3665         if (!strcmp(filename, "glsl/default.glsl"))
3666         {
3667                 if (!glslshaderstring)
3668                 {
3669                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3670                         if (glslshaderstring)
3671                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3672                         else
3673                                 glslshaderstring = (char *)builtinshaderstring;
3674                 }
3675                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3676                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3677                 return shaderstring;
3678         }
3679         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3680         if (shaderstring)
3681         {
3682                 if (printfromdisknotice)
3683                         Con_DPrintf("from disk %s... ", filename);
3684                 return shaderstring;
3685         }
3686         return shaderstring;
3687 }
3688
3689 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3690 {
3691         int i;
3692         int sampler;
3693         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3694         char *vertexstring, *geometrystring, *fragmentstring;
3695         char permutationname[256];
3696         int vertstrings_count = 0;
3697         int geomstrings_count = 0;
3698         int fragstrings_count = 0;
3699         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3700         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3701         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3702
3703         if (p->compiled)
3704                 return;
3705         p->compiled = true;
3706         p->program = 0;
3707
3708         permutationname[0] = 0;
3709         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3710         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3711         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3712
3713         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3714
3715         // the first pretext is which type of shader to compile as
3716         // (later these will all be bound together as a program object)
3717         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3718         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3719         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3720
3721         // the second pretext is the mode (for example a light source)
3722         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3723         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3724         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3725         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3726
3727         // now add all the permutation pretexts
3728         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3729         {
3730                 if (permutation & (1<<i))
3731                 {
3732                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3733                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3734                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3735                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3736                 }
3737                 else
3738                 {
3739                         // keep line numbers correct
3740                         vertstrings_list[vertstrings_count++] = "\n";
3741                         geomstrings_list[geomstrings_count++] = "\n";
3742                         fragstrings_list[fragstrings_count++] = "\n";
3743                 }
3744         }
3745
3746         // add static parms
3747         R_CompileShader_AddStaticParms(mode, permutation);
3748         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3749         vertstrings_count += shaderstaticparms_count;
3750         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3751         geomstrings_count += shaderstaticparms_count;
3752         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3753         fragstrings_count += shaderstaticparms_count;
3754
3755         // now append the shader text itself
3756         vertstrings_list[vertstrings_count++] = vertexstring;
3757         geomstrings_list[geomstrings_count++] = geometrystring;
3758         fragstrings_list[fragstrings_count++] = fragmentstring;
3759
3760         // if any sources were NULL, clear the respective list
3761         if (!vertexstring)
3762                 vertstrings_count = 0;
3763         if (!geometrystring)
3764                 geomstrings_count = 0;
3765         if (!fragmentstring)
3766                 fragstrings_count = 0;
3767
3768         // compile the shader program
3769         if (vertstrings_count + geomstrings_count + fragstrings_count)
3770                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3771         if (p->program)
3772         {
3773                 CHECKGLERROR
3774                 qglUseProgram(p->program);CHECKGLERROR
3775                 // look up all the uniform variable names we care about, so we don't
3776                 // have to look them up every time we set them
3777
3778                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
3779                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
3780                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
3781                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
3782                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
3783                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
3784                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
3785                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
3786                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
3787                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
3788                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
3789                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
3790                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
3791                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
3792                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
3793                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
3794                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
3795                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
3796                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
3797                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
3798                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
3799                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
3800                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
3801                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
3802                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
3803                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
3804                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
3805                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
3806                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
3807                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
3808                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
3809                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
3810                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
3811                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
3812                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
3813                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
3814                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
3815                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
3816                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
3817                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
3818                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
3819                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
3820                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
3821                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
3822                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
3823                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
3824                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
3825                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
3826                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
3827                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
3828                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
3829                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
3830                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
3831                 p->loc_OffsetMapping_Scale        = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
3832                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
3833                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
3834                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
3835                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
3836                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
3837                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
3838                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
3839                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
3840                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
3841                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
3842                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
3843                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
3844                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
3845                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
3846                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
3847                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
3848                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
3849                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
3850                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
3851                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
3852                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
3853                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
3854                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
3855                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
3856                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
3857                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
3858                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
3859                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
3860                 // initialize the samplers to refer to the texture units we use
3861                 p->tex_Texture_First = -1;
3862                 p->tex_Texture_Second = -1;
3863                 p->tex_Texture_GammaRamps = -1;
3864                 p->tex_Texture_Normal = -1;
3865                 p->tex_Texture_Color = -1;
3866                 p->tex_Texture_Gloss = -1;
3867                 p->tex_Texture_Glow = -1;
3868                 p->tex_Texture_SecondaryNormal = -1;
3869                 p->tex_Texture_SecondaryColor = -1;
3870                 p->tex_Texture_SecondaryGloss = -1;
3871                 p->tex_Texture_SecondaryGlow = -1;
3872                 p->tex_Texture_Pants = -1;
3873                 p->tex_Texture_Shirt = -1;
3874                 p->tex_Texture_FogHeightTexture = -1;
3875                 p->tex_Texture_FogMask = -1;
3876                 p->tex_Texture_Lightmap = -1;
3877                 p->tex_Texture_Deluxemap = -1;
3878                 p->tex_Texture_Attenuation = -1;
3879                 p->tex_Texture_Cube = -1;
3880                 p->tex_Texture_Refraction = -1;
3881                 p->tex_Texture_Reflection = -1;
3882                 p->tex_Texture_ShadowMap2D = -1;
3883                 p->tex_Texture_CubeProjection = -1;
3884                 p->tex_Texture_ScreenDepth = -1;
3885                 p->tex_Texture_ScreenNormalMap = -1;
3886                 p->tex_Texture_ScreenDiffuse = -1;
3887                 p->tex_Texture_ScreenSpecular = -1;
3888                 p->tex_Texture_ReflectMask = -1;
3889                 p->tex_Texture_ReflectCube = -1;
3890                 sampler = 0;
3891                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
3892                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
3893                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
3894                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
3895                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
3896                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
3897                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
3898                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
3899                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
3900                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
3901                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
3902                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
3903                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
3904                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
3905                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
3906                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
3907                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
3908                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
3909                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
3910                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
3911                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
3912                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
3913                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
3914                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
3915                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
3916                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
3917                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
3918                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
3919                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
3920                 CHECKGLERROR
3921                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
3922         }
3923         else
3924                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3925
3926         // free the strings
3927         if (vertexstring)
3928                 Mem_Free(vertexstring);
3929         if (geometrystring)
3930                 Mem_Free(geometrystring);
3931         if (fragmentstring)
3932                 Mem_Free(fragmentstring);
3933 }
3934
3935 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3936 {
3937         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3938         if (r_glsl_permutation != perm)
3939         {
3940                 r_glsl_permutation = perm;
3941                 if (!r_glsl_permutation->program)
3942                 {
3943                         if (!r_glsl_permutation->compiled)
3944                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3945                         if (!r_glsl_permutation->program)
3946                         {
3947                                 // remove features until we find a valid permutation
3948                                 int i;
3949                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3950                                 {
3951                                         // reduce i more quickly whenever it would not remove any bits
3952                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3953                                         if (!(permutation & j))
3954                                                 continue;
3955                                         permutation -= j;
3956                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3957                                         if (!r_glsl_permutation->compiled)
3958                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3959                                         if (r_glsl_permutation->program)
3960                                                 break;
3961                                 }
3962                                 if (i >= SHADERPERMUTATION_COUNT)
3963                                 {
3964                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3965                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3966                                         qglUseProgram(0);CHECKGLERROR
3967                                         return; // no bit left to clear, entire mode is broken
3968                                 }
3969                         }
3970                 }
3971                 CHECKGLERROR
3972                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
3973         }
3974         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3975         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3976         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
3977 }
3978
3979 #ifdef SUPPORTCG
3980 #include <Cg/cgGL.h>
3981 struct r_cg_permutation_s;
3982 typedef struct r_cg_permutation_s
3983 {
3984         /// hash lookup data
3985         struct r_cg_permutation_s *hashnext;
3986         unsigned int mode;
3987         unsigned int permutation;
3988
3989         /// indicates if we have tried compiling this permutation already
3990         qboolean compiled;
3991         /// 0 if compilation failed
3992         CGprogram vprogram;
3993         CGprogram fprogram;
3994         /// locations of detected parameters in programs, or NULL if not found
3995         CGparameter vp_EyePosition;
3996         CGparameter vp_FogPlane;
3997         CGparameter vp_LightDir;
3998         CGparameter vp_LightPosition;
3999         CGparameter vp_ModelToLight;
4000         CGparameter vp_TexMatrix;
4001         CGparameter vp_BackgroundTexMatrix;
4002         CGparameter vp_ModelViewProjectionMatrix;
4003         CGparameter vp_ModelViewMatrix;
4004         CGparameter vp_ShadowMapMatrix;
4005
4006         CGparameter fp_Texture_First;
4007         CGparameter fp_Texture_Second;
4008         CGparameter fp_Texture_GammaRamps;
4009         CGparameter fp_Texture_Normal;
4010         CGparameter fp_Texture_Color;
4011         CGparameter fp_Texture_Gloss;
4012         CGparameter fp_Texture_Glow;
4013         CGparameter fp_Texture_SecondaryNormal;
4014         CGparameter fp_Texture_SecondaryColor;
4015         CGparameter fp_Texture_SecondaryGloss;
4016         CGparameter fp_Texture_SecondaryGlow;
4017         CGparameter fp_Texture_Pants;
4018         CGparameter fp_Texture_Shirt;
4019         CGparameter fp_Texture_FogHeightTexture;
4020         CGparameter fp_Texture_FogMask;
4021         CGparameter fp_Texture_Lightmap;
4022         CGparameter fp_Texture_Deluxemap;
4023         CGparameter fp_Texture_Attenuation;
4024         CGparameter fp_Texture_Cube;
4025         CGparameter fp_Texture_Refraction;
4026         CGparameter fp_Texture_Reflection;
4027         CGparameter fp_Texture_ShadowMap2D;
4028         CGparameter fp_Texture_CubeProjection;
4029         CGparameter fp_Texture_ScreenDepth;
4030         CGparameter fp_Texture_ScreenNormalMap;
4031         CGparameter fp_Texture_ScreenDiffuse;
4032         CGparameter fp_Texture_ScreenSpecular;
4033         CGparameter fp_Texture_ReflectMask;
4034         CGparameter fp_Texture_ReflectCube;
4035         CGparameter fp_Alpha;
4036         CGparameter fp_BloomBlur_Parameters;
4037         CGparameter fp_ClientTime;
4038         CGparameter fp_Color_Ambient;
4039         CGparameter fp_Color_Diffuse;
4040         CGparameter fp_Color_Specular;
4041         CGparameter fp_Color_Glow;
4042         CGparameter fp_Color_Pants;
4043         CGparameter fp_Color_Shirt;
4044         CGparameter fp_DeferredColor_Ambient;
4045         CGparameter fp_DeferredColor_Diffuse;
4046         CGparameter fp_DeferredColor_Specular;
4047         CGparameter fp_DeferredMod_Diffuse;
4048         CGparameter fp_DeferredMod_Specular;
4049         CGparameter fp_DistortScaleRefractReflect;
4050         CGparameter fp_EyePosition;
4051         CGparameter fp_FogColor;
4052         CGparameter fp_FogHeightFade;
4053         CGparameter fp_FogPlane;
4054         CGparameter fp_FogPlaneViewDist;
4055         CGparameter fp_FogRangeRecip;
4056         CGparameter fp_LightColor;
4057         CGparameter fp_LightDir;
4058         CGparameter fp_LightPosition;
4059         CGparameter fp_OffsetMapping_Scale;
4060         CGparameter fp_PixelSize;
4061         CGparameter fp_ReflectColor;
4062         CGparameter fp_ReflectFactor;
4063         CGparameter fp_ReflectOffset;
4064         CGparameter fp_RefractColor;
4065         CGparameter fp_Saturation;
4066         CGparameter fp_ScreenCenterRefractReflect;
4067         CGparameter fp_ScreenScaleRefractReflect;
4068         CGparameter fp_ScreenToDepth;
4069         CGparameter fp_ShadowMap_Parameters;
4070         CGparameter fp_ShadowMap_TextureScale;
4071         CGparameter fp_SpecularPower;
4072         CGparameter fp_UserVec1;
4073         CGparameter fp_UserVec2;
4074         CGparameter fp_UserVec3;
4075         CGparameter fp_UserVec4;
4076         CGparameter fp_ViewTintColor;
4077         CGparameter fp_ViewToLight;
4078         CGparameter fp_PixelToScreenTexCoord;
4079         CGparameter fp_ModelToReflectCube;
4080         CGparameter fp_BloomColorSubtract;
4081         CGparameter fp_NormalmapScrollBlend;
4082 }
4083 r_cg_permutation_t;
4084
4085 /// information about each possible shader permutation
4086 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4087 /// currently selected permutation
4088 r_cg_permutation_t *r_cg_permutation;
4089 /// storage for permutations linked in the hash table
4090 memexpandablearray_t r_cg_permutationarray;
4091
4092 #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));}}
4093
4094 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4095 {
4096         //unsigned int hashdepth = 0;
4097         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4098         r_cg_permutation_t *p;
4099         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4100         {
4101                 if (p->mode == mode && p->permutation == permutation)
4102                 {
4103                         //if (hashdepth > 10)
4104                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4105                         return p;
4106                 }
4107                 //hashdepth++;
4108         }
4109         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4110         p->mode = mode;
4111         p->permutation = permutation;
4112         p->hashnext = r_cg_permutationhash[mode][hashindex];
4113         r_cg_permutationhash[mode][hashindex] = p;
4114         //if (hashdepth > 10)
4115         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4116         return p;
4117 }
4118
4119 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4120 {
4121         char *shaderstring;
4122         if (!filename || !filename[0])
4123                 return NULL;
4124         if (!strcmp(filename, "hlsl/default.hlsl"))
4125         {
4126                 if (!hlslshaderstring)
4127                 {
4128                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4129                         if (hlslshaderstring)
4130                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4131                         else
4132                                 hlslshaderstring = (char *)builtinhlslshaderstring;
4133                 }
4134                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4135                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4136                 return shaderstring;
4137         }
4138         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4139         if (shaderstring)
4140         {
4141                 if (printfromdisknotice)
4142                         Con_DPrintf("from disk %s... ", filename);
4143                 return shaderstring;
4144         }
4145         return shaderstring;
4146 }
4147
4148 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4149 {
4150         // TODO: load or create .fp and .vp shader files
4151 }
4152
4153 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4154 {
4155         int i;
4156         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4157         int vertstring_length = 0;
4158         int geomstring_length = 0;
4159         int fragstring_length = 0;
4160         char *t;
4161         char *vertexstring, *geometrystring, *fragmentstring;
4162         char *vertstring, *geomstring, *fragstring;
4163         char permutationname[256];
4164         char cachename[256];
4165         CGprofile vertexProfile;
4166         CGprofile fragmentProfile;
4167         int vertstrings_count = 0;
4168         int geomstrings_count = 0;
4169         int fragstrings_count = 0;
4170         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4171         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4172         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4173
4174         if (p->compiled)
4175                 return;
4176         p->compiled = true;
4177         p->vprogram = NULL;
4178         p->fprogram = NULL;
4179
4180         permutationname[0] = 0;
4181         cachename[0] = 0;
4182         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4183         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4184         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4185
4186         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4187         strlcat(cachename, "cggl/", sizeof(cachename));
4188
4189         // the first pretext is which type of shader to compile as
4190         // (later these will all be bound together as a program object)
4191         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4192         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4193         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4194
4195         // the second pretext is the mode (for example a light source)
4196         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4197         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4198         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4199         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4200         strlcat(cachename, modeinfo->name, sizeof(cachename));
4201
4202         // now add all the permutation pretexts
4203         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4204         {
4205                 if (permutation & (1<<i))
4206                 {
4207                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4208                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4209                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4210                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4211                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4212                 }
4213                 else
4214                 {
4215                         // keep line numbers correct
4216                         vertstrings_list[vertstrings_count++] = "\n";
4217                         geomstrings_list[geomstrings_count++] = "\n";
4218                         fragstrings_list[fragstrings_count++] = "\n";
4219                 }
4220         }
4221
4222         // add static parms
4223         R_CompileShader_AddStaticParms(mode, permutation);
4224         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4225         vertstrings_count += shaderstaticparms_count;
4226         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4227         geomstrings_count += shaderstaticparms_count;
4228         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4229         fragstrings_count += shaderstaticparms_count;
4230
4231         // replace spaces in the cachename with _ characters
4232         for (i = 0;cachename[i];i++)
4233                 if (cachename[i] == ' ')
4234                         cachename[i] = '_';
4235
4236         // now append the shader text itself
4237         vertstrings_list[vertstrings_count++] = vertexstring;
4238         geomstrings_list[geomstrings_count++] = geometrystring;
4239         fragstrings_list[fragstrings_count++] = fragmentstring;
4240
4241         // if any sources were NULL, clear the respective list
4242         if (!vertexstring)
4243                 vertstrings_count = 0;
4244         if (!geometrystring)
4245                 geomstrings_count = 0;
4246         if (!fragmentstring)
4247                 fragstrings_count = 0;
4248
4249         vertstring_length = 0;
4250         for (i = 0;i < vertstrings_count;i++)
4251                 vertstring_length += strlen(vertstrings_list[i]);
4252         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4253         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4254                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4255
4256         geomstring_length = 0;
4257         for (i = 0;i < geomstrings_count;i++)
4258                 geomstring_length += strlen(geomstrings_list[i]);
4259         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4260         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4261                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4262
4263         fragstring_length = 0;
4264         for (i = 0;i < fragstrings_count;i++)
4265                 fragstring_length += strlen(fragstrings_list[i]);
4266         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4267         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4268                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4269
4270         CHECKGLERROR
4271         CHECKCGERROR
4272         //vertexProfile = CG_PROFILE_ARBVP1;
4273         //fragmentProfile = CG_PROFILE_ARBFP1;
4274         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4275         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4276         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4277         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4278         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4279         CHECKGLERROR
4280
4281         // try to load the cached shader, or generate one
4282         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4283
4284         // if caching failed, do a dynamic compile for now
4285         CHECKCGERROR
4286         if (vertstring[0] && !p->vprogram)
4287                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4288         CHECKCGERROR
4289         if (fragstring[0] && !p->fprogram)
4290                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4291         CHECKCGERROR
4292
4293         // look up all the uniform variable names we care about, so we don't
4294         // have to look them up every time we set them
4295         if (p->vprogram)
4296         {
4297                 CHECKCGERROR
4298                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4299                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4300                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4301                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4302                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4303                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4304                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4305                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4306                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4307                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4308                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4309                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4310                 CHECKCGERROR
4311         }
4312         if (p->fprogram)
4313         {
4314                 CHECKCGERROR
4315                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4316                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4317                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4318                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4319                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4320                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4321                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4322                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4323                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4324                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4325                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4326                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4327                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4328                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4329                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4330                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4331                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4332                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4333                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4334                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4335                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4336                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4337                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4338                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4339                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4340                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4341                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4342                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4343                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4344                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4345                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4346                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4347                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4348                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4349                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4350                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4351                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4352                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4353                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4354                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4355                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4356                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4357                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4358                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4359                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4360                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4361                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4362                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4363                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4364                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4365                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4366                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4367                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4368                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4369                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4370                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4371                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4372                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4373                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4374                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4375                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4376                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4377                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4378                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4379                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4380                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4381                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4382                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4383                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4384                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4385                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4386                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4387                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4388                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4389                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4390                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4391                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4392                 p->fp_NormalmapScrollBlend       = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4393                 CHECKCGERROR
4394         }
4395
4396         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4397                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4398         else
4399                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4400
4401         // free the strings
4402         if (vertstring)
4403                 Mem_Free(vertstring);
4404         if (geomstring)
4405                 Mem_Free(geomstring);
4406         if (fragstring)
4407                 Mem_Free(fragstring);
4408         if (vertexstring)
4409                 Mem_Free(vertexstring);
4410         if (geometrystring)
4411                 Mem_Free(geometrystring);
4412         if (fragmentstring)
4413                 Mem_Free(fragmentstring);
4414 }
4415
4416 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4417 {
4418         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4419         CHECKGLERROR
4420         CHECKCGERROR
4421         if (r_cg_permutation != perm)
4422         {
4423                 r_cg_permutation = perm;
4424                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4425                 {
4426                         if (!r_cg_permutation->compiled)
4427                                 R_CG_CompilePermutation(perm, mode, permutation);
4428                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4429                         {
4430                                 // remove features until we find a valid permutation
4431                                 int i;
4432                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4433                                 {
4434                                         // reduce i more quickly whenever it would not remove any bits
4435                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4436                                         if (!(permutation & j))
4437                                                 continue;
4438                                         permutation -= j;
4439                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4440                                         if (!r_cg_permutation->compiled)
4441                                                 R_CG_CompilePermutation(perm, mode, permutation);
4442                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4443                                                 break;
4444                                 }
4445                                 if (i >= SHADERPERMUTATION_COUNT)
4446                                 {
4447                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4448                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4449                                         return; // no bit left to clear, entire mode is broken
4450                                 }
4451                         }
4452                 }
4453                 CHECKGLERROR
4454                 CHECKCGERROR
4455                 if (r_cg_permutation->vprogram)
4456                 {
4457                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4458                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4459                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4460                 }
4461                 else
4462                 {
4463                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4464                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4465                 }
4466                 if (r_cg_permutation->fprogram)
4467                 {
4468                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4469                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4470                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4471                 }
4472                 else
4473                 {
4474                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4475                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4476                 }
4477         }
4478         CHECKCGERROR
4479         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4480         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4481         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4482 }
4483
4484 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4485 {
4486         cgGLSetTextureParameter(param, R_GetTexture(tex));
4487         cgGLEnableTextureParameter(param);
4488 }
4489 #endif
4490
4491 #ifdef SUPPORTD3D
4492
4493 #ifdef SUPPORTD3D
4494 #include <d3d9.h>
4495 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4496 extern D3DCAPS9 vid_d3d9caps;
4497 #endif
4498
4499 struct r_hlsl_permutation_s;
4500 typedef struct r_hlsl_permutation_s
4501 {
4502         /// hash lookup data
4503         struct r_hlsl_permutation_s *hashnext;
4504         unsigned int mode;
4505         unsigned int permutation;
4506
4507         /// indicates if we have tried compiling this permutation already
4508         qboolean compiled;
4509         /// NULL if compilation failed
4510         IDirect3DVertexShader9 *vertexshader;
4511         IDirect3DPixelShader9 *pixelshader;
4512 }
4513 r_hlsl_permutation_t;
4514
4515 typedef enum D3DVSREGISTER_e
4516 {
4517         D3DVSREGISTER_TexMatrix = 0, // float4x4
4518         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4519         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4520         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4521         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4522         D3DVSREGISTER_ModelToLight = 20, // float4x4
4523         D3DVSREGISTER_EyePosition = 24,
4524         D3DVSREGISTER_FogPlane = 25,
4525         D3DVSREGISTER_LightDir = 26,
4526         D3DVSREGISTER_LightPosition = 27,
4527 }
4528 D3DVSREGISTER_t;
4529
4530 typedef enum D3DPSREGISTER_e
4531 {
4532         D3DPSREGISTER_Alpha = 0,
4533         D3DPSREGISTER_BloomBlur_Parameters = 1,
4534         D3DPSREGISTER_ClientTime = 2,
4535         D3DPSREGISTER_Color_Ambient = 3,
4536         D3DPSREGISTER_Color_Diffuse = 4,
4537         D3DPSREGISTER_Color_Specular = 5,
4538         D3DPSREGISTER_Color_Glow = 6,
4539         D3DPSREGISTER_Color_Pants = 7,
4540         D3DPSREGISTER_Color_Shirt = 8,
4541         D3DPSREGISTER_DeferredColor_Ambient = 9,
4542         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4543         D3DPSREGISTER_DeferredColor_Specular = 11,
4544         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4545         D3DPSREGISTER_DeferredMod_Specular = 13,
4546         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4547         D3DPSREGISTER_EyePosition = 15, // unused
4548         D3DPSREGISTER_FogColor = 16,
4549         D3DPSREGISTER_FogHeightFade = 17,
4550         D3DPSREGISTER_FogPlane = 18,
4551         D3DPSREGISTER_FogPlaneViewDist = 19,
4552         D3DPSREGISTER_FogRangeRecip = 20,
4553         D3DPSREGISTER_LightColor = 21,
4554         D3DPSREGISTER_LightDir = 22, // unused
4555         D3DPSREGISTER_LightPosition = 23,
4556         D3DPSREGISTER_OffsetMapping_Scale = 24,
4557         D3DPSREGISTER_PixelSize = 25,
4558         D3DPSREGISTER_ReflectColor = 26,
4559         D3DPSREGISTER_ReflectFactor = 27,
4560         D3DPSREGISTER_ReflectOffset = 28,
4561         D3DPSREGISTER_RefractColor = 29,
4562         D3DPSREGISTER_Saturation = 30,
4563         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4564         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4565         D3DPSREGISTER_ScreenToDepth = 33,
4566         D3DPSREGISTER_ShadowMap_Parameters = 34,
4567         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4568         D3DPSREGISTER_SpecularPower = 36,
4569         D3DPSREGISTER_UserVec1 = 37,
4570         D3DPSREGISTER_UserVec2 = 38,
4571         D3DPSREGISTER_UserVec3 = 39,
4572         D3DPSREGISTER_UserVec4 = 40,
4573         D3DPSREGISTER_ViewTintColor = 41,
4574         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4575         D3DPSREGISTER_BloomColorSubtract = 43,
4576         D3DPSREGISTER_ViewToLight = 44, // float4x4
4577         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4578         D3DPSREGISTER_NormalmapScrollBlend = 52,
4579         // next at 53
4580 }
4581 D3DPSREGISTER_t;
4582
4583 /// information about each possible shader permutation
4584 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4585 /// currently selected permutation
4586 r_hlsl_permutation_t *r_hlsl_permutation;
4587 /// storage for permutations linked in the hash table
4588 memexpandablearray_t r_hlsl_permutationarray;
4589
4590 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4591 {
4592         //unsigned int hashdepth = 0;
4593         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4594         r_hlsl_permutation_t *p;
4595         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4596         {
4597                 if (p->mode == mode && p->permutation == permutation)
4598                 {
4599                         //if (hashdepth > 10)
4600                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4601                         return p;
4602                 }
4603                 //hashdepth++;
4604         }
4605         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4606         p->mode = mode;
4607         p->permutation = permutation;
4608         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4609         r_hlsl_permutationhash[mode][hashindex] = p;
4610         //if (hashdepth > 10)
4611         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4612         return p;
4613 }
4614
4615 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4616 {
4617         char *shaderstring;
4618         if (!filename || !filename[0])
4619                 return NULL;
4620         if (!strcmp(filename, "hlsl/default.hlsl"))
4621         {
4622                 if (!hlslshaderstring)
4623                 {
4624                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4625                         if (hlslshaderstring)
4626                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4627                         else
4628                                 hlslshaderstring = (char *)builtinhlslshaderstring;
4629                 }
4630                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4631                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4632                 return shaderstring;
4633         }
4634         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4635         if (shaderstring)
4636         {
4637                 if (printfromdisknotice)
4638                         Con_DPrintf("from disk %s... ", filename);
4639                 return shaderstring;
4640         }
4641         return shaderstring;
4642 }
4643
4644 #include <d3dx9.h>
4645 //#include <d3dx9shader.h>
4646 //#include <d3dx9mesh.h>
4647
4648 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4649 {
4650         DWORD *vsbin = NULL;
4651         DWORD *psbin = NULL;
4652         fs_offset_t vsbinsize;
4653         fs_offset_t psbinsize;
4654 //      IDirect3DVertexShader9 *vs = NULL;
4655 //      IDirect3DPixelShader9 *ps = NULL;
4656         ID3DXBuffer *vslog = NULL;
4657         ID3DXBuffer *vsbuffer = NULL;
4658         ID3DXConstantTable *vsconstanttable = NULL;
4659         ID3DXBuffer *pslog = NULL;
4660         ID3DXBuffer *psbuffer = NULL;
4661         ID3DXConstantTable *psconstanttable = NULL;
4662         int vsresult = 0;
4663         int psresult = 0;
4664         char temp[MAX_INPUTLINE];
4665         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4666         qboolean debugshader = gl_paranoid.integer != 0;
4667         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4668         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4669         if (!debugshader)
4670         {
4671                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4672                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4673         }
4674         if ((!vsbin && vertstring) || (!psbin && fragstring))
4675         {
4676                 const char* dllnames_d3dx9 [] =
4677                 {
4678                         "d3dx9_43.dll",
4679                         "d3dx9_42.dll",
4680                         "d3dx9_41.dll",
4681                         "d3dx9_40.dll",
4682                         "d3dx9_39.dll",
4683                         "d3dx9_38.dll",
4684                         "d3dx9_37.dll",
4685                         "d3dx9_36.dll",
4686                         "d3dx9_35.dll",
4687                         "d3dx9_34.dll",
4688                         "d3dx9_33.dll",
4689                         "d3dx9_32.dll",
4690                         "d3dx9_31.dll",
4691                         "d3dx9_30.dll",
4692                         "d3dx9_29.dll",
4693                         "d3dx9_28.dll",
4694                         "d3dx9_27.dll",
4695                         "d3dx9_26.dll",
4696                         "d3dx9_25.dll",
4697                         "d3dx9_24.dll",
4698                         NULL
4699                 };
4700                 dllhandle_t d3dx9_dll = NULL;
4701                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4702                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4703                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4704                 dllfunction_t d3dx9_dllfuncs[] =
4705                 {
4706                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4707                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4708                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4709                         {NULL, NULL}
4710                 };
4711                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4712                 {
4713                         DWORD shaderflags = 0;
4714                         if (debugshader)
4715                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4716                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4717                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4718                         if (vertstring && vertstring[0])
4719                         {
4720                                 if (debugshader)
4721                                 {
4722 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4723 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4724                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4725                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4726                                 }
4727                                 else
4728                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4729                                 if (vsbuffer)
4730                                 {
4731                                         vsbinsize = vsbuffer->GetBufferSize();
4732                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4733                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4734                                         vsbuffer->Release();
4735                                 }
4736                                 if (vslog)
4737                                 {
4738                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4739                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4740                                         vslog->Release();
4741                                 }
4742                         }
4743                         if (fragstring && fragstring[0])
4744                         {
4745                                 if (debugshader)
4746                                 {
4747 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4748 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4749                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4750                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4751                                 }
4752                                 else
4753                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4754                                 if (psbuffer)
4755                                 {
4756                                         psbinsize = psbuffer->GetBufferSize();
4757                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4758                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4759                                         psbuffer->Release();
4760                                 }
4761                                 if (pslog)
4762                                 {
4763                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4764                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4765                                         pslog->Release();
4766                                 }
4767                         }
4768                         Sys_UnloadLibrary(&d3dx9_dll);
4769                 }
4770                 else
4771                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4772         }
4773         if (vsbin && psbin)
4774         {
4775                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4776                 if (FAILED(vsresult))
4777                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4778                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4779                 if (FAILED(psresult))
4780                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4781         }
4782         // free the shader data
4783         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4784         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4785 }
4786
4787 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4788 {
4789         int i;
4790         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4791         int vertstring_length = 0;
4792         int geomstring_length = 0;
4793         int fragstring_length = 0;
4794         char *t;
4795         char *vertexstring, *geometrystring, *fragmentstring;
4796         char *vertstring, *geomstring, *fragstring;
4797         char permutationname[256];
4798         char cachename[256];
4799         int vertstrings_count = 0;
4800         int geomstrings_count = 0;
4801         int fragstrings_count = 0;
4802         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4803         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4804         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4805
4806         if (p->compiled)
4807                 return;
4808         p->compiled = true;
4809         p->vertexshader = NULL;
4810         p->pixelshader = NULL;
4811
4812         permutationname[0] = 0;
4813         cachename[0] = 0;
4814         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4815         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4816         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4817
4818         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4819         strlcat(cachename, "hlsl/", sizeof(cachename));
4820
4821         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4822         vertstrings_count = 0;
4823         geomstrings_count = 0;
4824         fragstrings_count = 0;
4825         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4826         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4827         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4828
4829         // the first pretext is which type of shader to compile as
4830         // (later these will all be bound together as a program object)
4831         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4832         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4833         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4834
4835         // the second pretext is the mode (for example a light source)
4836         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4837         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4838         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4839         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4840         strlcat(cachename, modeinfo->name, sizeof(cachename));
4841
4842         // now add all the permutation pretexts
4843         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4844         {
4845                 if (permutation & (1<<i))
4846                 {
4847                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4848                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4849                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4850                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4851                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4852                 }
4853                 else
4854                 {
4855                         // keep line numbers correct
4856                         vertstrings_list[vertstrings_count++] = "\n";
4857                         geomstrings_list[geomstrings_count++] = "\n";
4858                         fragstrings_list[fragstrings_count++] = "\n";
4859                 }
4860         }
4861
4862         // add static parms
4863         R_CompileShader_AddStaticParms(mode, permutation);
4864         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4865         vertstrings_count += shaderstaticparms_count;
4866         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4867         geomstrings_count += shaderstaticparms_count;
4868         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4869         fragstrings_count += shaderstaticparms_count;
4870
4871         // replace spaces in the cachename with _ characters
4872         for (i = 0;cachename[i];i++)
4873                 if (cachename[i] == ' ')
4874                         cachename[i] = '_';
4875
4876         // now append the shader text itself
4877         vertstrings_list[vertstrings_count++] = vertexstring;
4878         geomstrings_list[geomstrings_count++] = geometrystring;
4879         fragstrings_list[fragstrings_count++] = fragmentstring;
4880
4881         // if any sources were NULL, clear the respective list
4882         if (!vertexstring)
4883                 vertstrings_count = 0;
4884         if (!geometrystring)
4885                 geomstrings_count = 0;
4886         if (!fragmentstring)
4887                 fragstrings_count = 0;
4888
4889         vertstring_length = 0;
4890         for (i = 0;i < vertstrings_count;i++)
4891                 vertstring_length += strlen(vertstrings_list[i]);
4892         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4893         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4894                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4895
4896         geomstring_length = 0;
4897         for (i = 0;i < geomstrings_count;i++)
4898                 geomstring_length += strlen(geomstrings_list[i]);
4899         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4900         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4901                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4902
4903         fragstring_length = 0;
4904         for (i = 0;i < fragstrings_count;i++)
4905                 fragstring_length += strlen(fragstrings_list[i]);
4906         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4907         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4908                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4909
4910         // try to load the cached shader, or generate one
4911         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4912
4913         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4914                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4915         else
4916                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4917
4918         // free the strings
4919         if (vertstring)
4920                 Mem_Free(vertstring);
4921         if (geomstring)
4922                 Mem_Free(geomstring);
4923         if (fragstring)
4924                 Mem_Free(fragstring);
4925         if (vertexstring)
4926                 Mem_Free(vertexstring);
4927         if (geometrystring)
4928                 Mem_Free(geometrystring);
4929         if (fragmentstring)
4930                 Mem_Free(fragmentstring);
4931 }
4932
4933 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4934 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4935 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);}
4936 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);}
4937 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);}
4938 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);}
4939
4940 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4941 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4942 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);}
4943 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);}
4944 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);}
4945 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);}
4946
4947 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4948 {
4949         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4950         if (r_hlsl_permutation != perm)
4951         {
4952                 r_hlsl_permutation = perm;
4953                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4954                 {
4955                         if (!r_hlsl_permutation->compiled)
4956                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4957                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4958                         {
4959                                 // remove features until we find a valid permutation
4960                                 int i;
4961                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4962                                 {
4963                                         // reduce i more quickly whenever it would not remove any bits
4964                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4965                                         if (!(permutation & j))
4966                                                 continue;
4967                                         permutation -= j;
4968                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4969                                         if (!r_hlsl_permutation->compiled)
4970                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4971                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4972                                                 break;
4973                                 }
4974                                 if (i >= SHADERPERMUTATION_COUNT)
4975                                 {
4976                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4977                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4978                                         return; // no bit left to clear, entire mode is broken
4979                                 }
4980                         }
4981                 }
4982                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4983                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4984         }
4985         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4986         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4987         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4988 }
4989 #endif
4990
4991 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
4992 {
4993         DPSOFTRAST_SetShader(mode, permutation);
4994         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
4995         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
4996         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
4997 }
4998
4999 void R_GLSL_Restart_f(void)
5000 {
5001         unsigned int i, limit;
5002         if (glslshaderstring && glslshaderstring != builtinshaderstring)
5003                 Mem_Free(glslshaderstring);
5004         glslshaderstring = NULL;
5005         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
5006                 Mem_Free(hlslshaderstring);
5007         hlslshaderstring = NULL;
5008         switch(vid.renderpath)
5009         {
5010         case RENDERPATH_D3D9:
5011 #ifdef SUPPORTD3D
5012                 {
5013                         r_hlsl_permutation_t *p;
5014                         r_hlsl_permutation = NULL;
5015 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5016 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5017 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5018 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5019                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
5020                         for (i = 0;i < limit;i++)
5021                         {
5022                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
5023                                 {
5024                                         if (p->vertexshader)
5025                                                 IDirect3DVertexShader9_Release(p->vertexshader);
5026                                         if (p->pixelshader)
5027                                                 IDirect3DPixelShader9_Release(p->pixelshader);
5028                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
5029                                 }
5030                         }
5031                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
5032                 }
5033 #endif
5034                 break;
5035         case RENDERPATH_D3D10:
5036                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5037                 break;
5038         case RENDERPATH_D3D11:
5039                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5040                 break;
5041         case RENDERPATH_GL20:
5042         case RENDERPATH_GLES2:
5043                 {
5044                         r_glsl_permutation_t *p;
5045                         r_glsl_permutation = NULL;
5046                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5047                         for (i = 0;i < limit;i++)
5048                         {
5049                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5050                                 {
5051                                         GL_Backend_FreeProgram(p->program);
5052                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5053                                 }
5054                         }
5055                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5056                 }
5057                 break;
5058         case RENDERPATH_CGGL:
5059 #ifdef SUPPORTCG
5060                 {
5061                         r_cg_permutation_t *p;
5062                         r_cg_permutation = NULL;
5063                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5064                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5065                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5066                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5067                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5068                         for (i = 0;i < limit;i++)
5069                         {
5070                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5071                                 {
5072                                         if (p->vprogram)
5073                                                 cgDestroyProgram(p->vprogram);
5074                                         if (p->fprogram)
5075                                                 cgDestroyProgram(p->fprogram);
5076                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5077                                 }
5078                         }
5079                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5080                 }
5081 #endif
5082                 break;
5083         case RENDERPATH_GL13:
5084         case RENDERPATH_GL11:
5085                 break;
5086         case RENDERPATH_SOFT:
5087                 break;
5088         }
5089 }
5090
5091 void R_GLSL_DumpShader_f(void)
5092 {
5093         int i;
5094         qfile_t *file;
5095
5096         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5097         if (file)
5098         {
5099                 FS_Print(file, "/* The engine may define the following macros:\n");
5100                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5101                 for (i = 0;i < SHADERMODE_COUNT;i++)
5102                         FS_Print(file, glslshadermodeinfo[i].pretext);
5103                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5104                         FS_Print(file, shaderpermutationinfo[i].pretext);
5105                 FS_Print(file, "*/\n");
5106                 FS_Print(file, builtinshaderstring);
5107                 FS_Close(file);
5108                 Con_Printf("glsl/default.glsl written\n");
5109         }
5110         else
5111                 Con_Printf("failed to write to glsl/default.glsl\n");
5112
5113         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5114         if (file)
5115         {
5116                 FS_Print(file, "/* The engine may define the following macros:\n");
5117                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5118                 for (i = 0;i < SHADERMODE_COUNT;i++)
5119                         FS_Print(file, hlslshadermodeinfo[i].pretext);
5120                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5121                         FS_Print(file, shaderpermutationinfo[i].pretext);
5122                 FS_Print(file, "*/\n");
5123                 FS_Print(file, builtinhlslshaderstring);
5124                 FS_Close(file);
5125                 Con_Printf("hlsl/default.hlsl written\n");
5126         }
5127         else
5128                 Con_Printf("failed to write to hlsl/default.hlsl\n");
5129 }
5130
5131 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5132 {
5133         if (!second)
5134                 texturemode = GL_MODULATE;
5135         switch (vid.renderpath)
5136         {
5137         case RENDERPATH_D3D9:
5138 #ifdef SUPPORTD3D
5139                 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))));
5140                 R_Mesh_TexBind(GL20TU_FIRST , first );
5141                 R_Mesh_TexBind(GL20TU_SECOND, second);
5142 #endif
5143                 break;
5144         case RENDERPATH_D3D10:
5145                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5146                 break;
5147         case RENDERPATH_D3D11:
5148                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5149                 break;
5150         case RENDERPATH_GL20:
5151         case RENDERPATH_GLES2:
5152                 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))));
5153                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
5154                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
5155                 break;
5156         case RENDERPATH_CGGL:
5157 #ifdef SUPPORTCG
5158                 CHECKCGERROR
5159                 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))));
5160                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5161                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5162 #endif
5163                 break;
5164         case RENDERPATH_GL13:
5165                 R_Mesh_TexBind(0, first );
5166                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5167                 R_Mesh_TexBind(1, second);
5168                 if (second)
5169                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5170                 break;
5171         case RENDERPATH_GL11:
5172                 R_Mesh_TexBind(0, first );
5173                 break;
5174         case RENDERPATH_SOFT:
5175                 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))));
5176                 R_Mesh_TexBind(GL20TU_FIRST , first );
5177                 R_Mesh_TexBind(GL20TU_SECOND, second);
5178                 break;
5179         }
5180 }
5181
5182 void R_SetupShader_DepthOrShadow(void)
5183 {
5184         switch (vid.renderpath)
5185         {
5186         case RENDERPATH_D3D9:
5187 #ifdef SUPPORTD3D
5188                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5189 #endif
5190                 break;
5191         case RENDERPATH_D3D10:
5192                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5193                 break;
5194         case RENDERPATH_D3D11:
5195                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5196                 break;
5197         case RENDERPATH_GL20:
5198         case RENDERPATH_GLES2:
5199                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5200                 break;
5201         case RENDERPATH_CGGL:
5202 #ifdef SUPPORTCG
5203                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5204 #endif
5205                 break;
5206         case RENDERPATH_GL13:
5207                 R_Mesh_TexBind(0, 0);
5208                 R_Mesh_TexBind(1, 0);
5209                 break;
5210         case RENDERPATH_GL11:
5211                 R_Mesh_TexBind(0, 0);
5212                 break;
5213         case RENDERPATH_SOFT:
5214                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
5215                 break;
5216         }
5217 }
5218
5219 void R_SetupShader_ShowDepth(void)
5220 {
5221         switch (vid.renderpath)
5222         {
5223         case RENDERPATH_D3D9:
5224 #ifdef SUPPORTHLSL
5225                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5226 #endif
5227                 break;
5228         case RENDERPATH_D3D10:
5229                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5230                 break;
5231         case RENDERPATH_D3D11:
5232                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5233                 break;
5234         case RENDERPATH_GL20:
5235         case RENDERPATH_GLES2:
5236                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5237                 break;
5238         case RENDERPATH_CGGL:
5239 #ifdef SUPPORTCG
5240                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5241 #endif
5242                 break;
5243         case RENDERPATH_GL13:
5244                 break;
5245         case RENDERPATH_GL11:
5246                 break;
5247         case RENDERPATH_SOFT:
5248                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
5249                 break;
5250         }
5251 }
5252
5253 extern qboolean r_shadow_usingdeferredprepass;
5254 extern cvar_t r_shadow_deferred_8bitrange;
5255 extern rtexture_t *r_shadow_attenuationgradienttexture;
5256 extern rtexture_t *r_shadow_attenuation2dtexture;
5257 extern rtexture_t *r_shadow_attenuation3dtexture;
5258 extern qboolean r_shadow_usingshadowmap2d;
5259 extern qboolean r_shadow_usingshadowmaportho;
5260 extern float r_shadow_shadowmap_texturescale[2];
5261 extern float r_shadow_shadowmap_parameters[4];
5262 extern qboolean r_shadow_shadowmapvsdct;
5263 extern qboolean r_shadow_shadowmapsampler;
5264 extern int r_shadow_shadowmappcf;
5265 extern rtexture_t *r_shadow_shadowmap2dtexture;
5266 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5267 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5268 extern matrix4x4_t r_shadow_shadowmapmatrix;
5269 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5270 extern int r_shadow_prepass_width;
5271 extern int r_shadow_prepass_height;
5272 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5273 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5274 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5275 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5276 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5277 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5278 {
5279         // a blendfunc allows colormod if:
5280         // a) it can never keep the destination pixel invariant, or
5281         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5282         // this is to prevent unintended side effects from colormod
5283
5284         // in formulas:
5285         // IF there is a (s, sa) for which for all (d, da),
5286         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5287         // THEN, for this (s, sa) and all (colormod, d, da):
5288         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5289         // OBVIOUSLY, this means that
5290         //   s*colormod * src(s*colormod, d, sa, da) = 0
5291         //   dst(s*colormod, d, sa, da)              = 1
5292
5293         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5294
5295         // main condition to leave dst color invariant:
5296         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5297         //   src == GL_ZERO:
5298         //     s * 0 + d * dst(s, d, sa, da) == d
5299         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5300         //       => colormod is a problem for GL_SRC_COLOR only
5301         //   src == GL_ONE:
5302         //     s + d * dst(s, d, sa, da) == d
5303         //       => s == 0
5304         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5305         //       => colormod is never problematic for these
5306         //   src == GL_SRC_COLOR:
5307         //     s*s + d * dst(s, d, sa, da) == d
5308         //       => s == 0
5309         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5310         //       => colormod is never problematic for these
5311         //   src == GL_ONE_MINUS_SRC_COLOR:
5312         //     s*(1-s) + d * dst(s, d, sa, da) == d
5313         //       => s == 0 or s == 1
5314         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5315         //       => colormod is a problem for GL_SRC_COLOR only
5316         //   src == GL_DST_COLOR
5317         //     s*d + d * dst(s, d, sa, da) == d
5318         //       => s == 1
5319         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5320         //       => colormod is always a problem
5321         //     or
5322         //       => s == 0
5323         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5324         //       => colormod is never problematic for these
5325         //       => BUT, we do not know s! We must assume it is problematic
5326         //       then... except in GL_ONE case, where we know all invariant
5327         //       cases are fine
5328         //   src == GL_ONE_MINUS_DST_COLOR
5329         //     s*(1-d) + d * dst(s, d, sa, da) == d
5330         //       => s == 0 (1-d is impossible to handle for our desired result)
5331         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5332         //       => colormod is never problematic for these
5333         //   src == GL_SRC_ALPHA
5334         //     s*sa + d * dst(s, d, sa, da) == d
5335         //       => s == 0, or sa == 0
5336         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5337         //       => colormod breaks in the case GL_SRC_COLOR only
5338         //   src == GL_ONE_MINUS_SRC_ALPHA
5339         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5340         //       => s == 0, or sa == 1
5341         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5342         //       => colormod breaks in the case GL_SRC_COLOR only
5343         //   src == GL_DST_ALPHA
5344         //     s*da + d * dst(s, d, sa, da) == d
5345         //       => s == 0
5346         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5347         //       => colormod is never problematic for these
5348
5349         switch(src)
5350         {
5351                 case GL_ZERO:
5352                 case GL_ONE_MINUS_SRC_COLOR:
5353                 case GL_SRC_ALPHA:
5354                 case GL_ONE_MINUS_SRC_ALPHA:
5355                         if(dst == GL_SRC_COLOR)
5356                                 return false;
5357                         return true;
5358                 case GL_ONE:
5359                 case GL_SRC_COLOR:
5360                 case GL_ONE_MINUS_DST_COLOR:
5361                 case GL_DST_ALPHA:
5362                 case GL_ONE_MINUS_DST_ALPHA:
5363                         return true;
5364                 case GL_DST_COLOR:
5365                         if(dst == GL_ONE)
5366                                 return true;
5367                         return false;
5368                 default:
5369                         return false;
5370         }
5371 }
5372 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)
5373 {
5374         // select a permutation of the lighting shader appropriate to this
5375         // combination of texture, entity, light source, and fogging, only use the
5376         // minimum features necessary to avoid wasting rendering time in the
5377         // fragment shader on features that are not being used
5378         unsigned int permutation = 0;
5379         unsigned int mode = 0;
5380         qboolean allow_colormod;
5381         static float dummy_colormod[3] = {1, 1, 1};
5382         float *colormod = rsurface.colormod;
5383         float m16f[16];
5384         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5385         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5386                 permutation |= SHADERPERMUTATION_ALPHAKILL;
5387         if (rsurfacepass == RSURFPASS_BACKGROUND)
5388         {
5389                 // distorted background
5390                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5391                 {
5392                         mode = SHADERMODE_WATER;
5393                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5394                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5395                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
5396                         {
5397                                 // this is the right thing to do for wateralpha
5398                                 GL_BlendFunc(GL_ONE, GL_ZERO);
5399                                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5400                         }
5401                         else
5402                         {
5403                                 // this is the right thing to do for entity alpha
5404                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5405                                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5406                         }
5407                 }
5408                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5409                 {
5410                         mode = SHADERMODE_REFRACTION;
5411                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5412                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5413                 }
5414                 else
5415                 {
5416                         mode = SHADERMODE_GENERIC;
5417                         permutation |= SHADERPERMUTATION_DIFFUSE;
5418                         GL_BlendFunc(GL_ONE, GL_ZERO);
5419                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5420                 }
5421         }
5422         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5423         {
5424                 if (r_glsl_offsetmapping.integer)
5425                 {
5426                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5427                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5428                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5429                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5430                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5431                         {
5432                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5433                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5434                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5435                         }
5436                 }
5437                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5438                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5439                 // normalmap (deferred prepass), may use alpha test on diffuse
5440                 mode = SHADERMODE_DEFERREDGEOMETRY;
5441                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5442                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5443                 GL_BlendFunc(GL_ONE, GL_ZERO);
5444                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5445         }
5446         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5447         {
5448                 if (r_glsl_offsetmapping.integer)
5449                 {
5450                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5451                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5452                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5453                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5454                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5455                         {
5456                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5457                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5458                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5459                         }
5460                 }
5461                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5462                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5463                 // light source
5464                 mode = SHADERMODE_LIGHTSOURCE;
5465                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5466                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5467                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5468                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5469                 if (diffusescale > 0)
5470                         permutation |= SHADERPERMUTATION_DIFFUSE;
5471                 if (specularscale > 0)
5472                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5473                 if (r_refdef.fogenabled)
5474                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5475                 if (rsurface.texture->colormapping)
5476                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5477                 if (r_shadow_usingshadowmap2d)
5478                 {
5479                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5480                         if(r_shadow_shadowmapvsdct)
5481                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5482
5483                         if (r_shadow_shadowmapsampler)
5484                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5485                         if (r_shadow_shadowmappcf > 1)
5486                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5487                         else if (r_shadow_shadowmappcf)
5488                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5489                 }
5490                 if (rsurface.texture->reflectmasktexture)
5491                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5492                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5493                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5494         }
5495         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5496         {
5497                 if (r_glsl_offsetmapping.integer)
5498                 {
5499                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5500                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5501                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5502                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5503                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5504                         {
5505                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5506                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5507                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5508                         }
5509                 }
5510                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5511                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5512                 // unshaded geometry (fullbright or ambient model lighting)
5513                 mode = SHADERMODE_FLATCOLOR;
5514                 ambientscale = diffusescale = specularscale = 0;
5515                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5516                         permutation |= SHADERPERMUTATION_GLOW;
5517                 if (r_refdef.fogenabled)
5518                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5519                 if (rsurface.texture->colormapping)
5520                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5521                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5522                 {
5523                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5524                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5525
5526                         if (r_shadow_shadowmapsampler)
5527                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5528                         if (r_shadow_shadowmappcf > 1)
5529                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5530                         else if (r_shadow_shadowmappcf)
5531                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5532                 }
5533                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5534                         permutation |= SHADERPERMUTATION_REFLECTION;
5535                 if (rsurface.texture->reflectmasktexture)
5536                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5537                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5538                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5539         }
5540         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5541         {
5542                 if (r_glsl_offsetmapping.integer)
5543                 {
5544                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5545                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5546                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5547                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5548                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5549                         {
5550                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5551                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5552                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5553                         }
5554                 }
5555                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5556                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5557                 // directional model lighting
5558                 mode = SHADERMODE_LIGHTDIRECTION;
5559                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5560                         permutation |= SHADERPERMUTATION_GLOW;
5561                 permutation |= SHADERPERMUTATION_DIFFUSE;
5562                 if (specularscale > 0)
5563                         permutation |= SHADERPERMUTATION_SPECULAR;
5564                 if (r_refdef.fogenabled)
5565                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5566                 if (rsurface.texture->colormapping)
5567                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5568                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5569                 {
5570                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5571                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5572
5573                         if (r_shadow_shadowmapsampler)
5574                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5575                         if (r_shadow_shadowmappcf > 1)
5576                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5577                         else if (r_shadow_shadowmappcf)
5578                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5579                 }
5580                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5581                         permutation |= SHADERPERMUTATION_REFLECTION;
5582                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5583                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5584                 if (rsurface.texture->reflectmasktexture)
5585                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5586                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5587                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5588         }
5589         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5590         {
5591                 if (r_glsl_offsetmapping.integer)
5592                 {
5593                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5594                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5595                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5596                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5597                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5598                         {
5599                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5600                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5601                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5602                         }
5603                 }
5604                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5605                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5606                 // ambient model lighting
5607                 mode = SHADERMODE_LIGHTDIRECTION;
5608                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5609                         permutation |= SHADERPERMUTATION_GLOW;
5610                 if (r_refdef.fogenabled)
5611                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5612                 if (rsurface.texture->colormapping)
5613                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5614                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5615                 {
5616                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5617                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5618
5619                         if (r_shadow_shadowmapsampler)
5620                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5621                         if (r_shadow_shadowmappcf > 1)
5622                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5623                         else if (r_shadow_shadowmappcf)
5624                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5625                 }
5626                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5627                         permutation |= SHADERPERMUTATION_REFLECTION;
5628                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5629                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5630                 if (rsurface.texture->reflectmasktexture)
5631                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5632                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5633                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5634         }
5635         else
5636         {
5637                 if (r_glsl_offsetmapping.integer)
5638                 {
5639                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5640                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5641                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5642                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5643                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5644                         {
5645                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5646                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5647                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5648                         }
5649                 }
5650                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5651                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5652                 // lightmapped wall
5653                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5654                         permutation |= SHADERPERMUTATION_GLOW;
5655                 if (r_refdef.fogenabled)
5656                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5657                 if (rsurface.texture->colormapping)
5658                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5659                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5660                 {
5661                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5662                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5663
5664                         if (r_shadow_shadowmapsampler)
5665                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5666                         if (r_shadow_shadowmappcf > 1)
5667                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5668                         else if (r_shadow_shadowmappcf)
5669                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5670                 }
5671                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5672                         permutation |= SHADERPERMUTATION_REFLECTION;
5673                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5674                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5675                 if (rsurface.texture->reflectmasktexture)
5676                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5677                 if (FAKELIGHT_ENABLED)
5678                 {
5679                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5680                         mode = SHADERMODE_FAKELIGHT;
5681                         permutation |= SHADERPERMUTATION_DIFFUSE;
5682                         if (specularscale > 0)
5683                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5684                 }
5685                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5686                 {
5687                         // deluxemapping (light direction texture)
5688                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5689                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5690                         else
5691                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5692                         permutation |= SHADERPERMUTATION_DIFFUSE;
5693                         if (specularscale > 0)
5694                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5695                 }
5696                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5697                 {
5698                         // fake deluxemapping (uniform light direction in tangentspace)
5699                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5700                         permutation |= SHADERPERMUTATION_DIFFUSE;
5701                         if (specularscale > 0)
5702                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5703                 }
5704                 else if (rsurface.uselightmaptexture)
5705                 {
5706                         // ordinary lightmapping (q1bsp, q3bsp)
5707                         mode = SHADERMODE_LIGHTMAP;
5708                 }
5709                 else
5710                 {
5711                         // ordinary vertex coloring (q3bsp)
5712                         mode = SHADERMODE_VERTEXCOLOR;
5713                 }
5714                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5715                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5716         }
5717         if(!allow_colormod)
5718                 colormod = dummy_colormod;
5719         switch(vid.renderpath)
5720         {
5721         case RENDERPATH_D3D9:
5722 #ifdef SUPPORTD3D
5723                 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);
5724                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5725                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5726                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5727                 if (mode == SHADERMODE_LIGHTSOURCE)
5728                 {
5729                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5730                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5731                 }
5732                 else
5733                 {
5734                         if (mode == SHADERMODE_LIGHTDIRECTION)
5735                         {
5736                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5737                         }
5738                 }
5739                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5740                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5741                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5742                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5743                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5744
5745                 if (mode == SHADERMODE_LIGHTSOURCE)
5746                 {
5747                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5748                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5749                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5750                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5751                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5752
5753                         // additive passes are only darkened by fog, not tinted
5754                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5755                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5756                 }
5757                 else
5758                 {
5759                         if (mode == SHADERMODE_FLATCOLOR)
5760                         {
5761                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5762                         }
5763                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5764                         {
5765                                 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]);
5766                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5767                                 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);
5768                                 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);
5769                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5770                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5771                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5772                         }
5773                         else
5774                         {
5775                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5776                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5777                                 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);
5778                                 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);
5779                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5780                         }
5781                         // additive passes are only darkened by fog, not tinted
5782                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5783                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5784                         else
5785                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5786                         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);
5787                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5788                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5789                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5790                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5791                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5792                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5793                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5794                         if (mode == SHADERMODE_WATER)
5795                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5796                 }
5797                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5798                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5799                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5800                 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));
5801                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5802                 if (rsurface.texture->pantstexture)
5803                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5804                 else
5805                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5806                 if (rsurface.texture->shirttexture)
5807                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5808                 else
5809                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5810                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5811                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5812                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5813                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5814                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5815                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5816                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5817
5818                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5819                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5820                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5821                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5822                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5823                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5824                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5825                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5826                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5827                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5828                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5829                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5830                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5831                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5832                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5833                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5834                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5835                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5836                 {
5837                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5838                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5839                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5840                 }
5841                 else
5842                 {
5843                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5844                 }
5845 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5846 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5847                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5848                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5849                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5850                 {
5851                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5852                         if (rsurface.rtlight)
5853                         {
5854                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5855                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5856                         }
5857                 }
5858 #endif
5859                 break;
5860         case RENDERPATH_D3D10:
5861                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5862                 break;
5863         case RENDERPATH_D3D11:
5864                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5865                 break;
5866         case RENDERPATH_GL20:
5867         case RENDERPATH_GLES2:
5868                 if (!vid.useinterleavedarrays)
5869                 {
5870                         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);
5871                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5872                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5873                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5874                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5875                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5876                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5877                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5878                 }
5879                 else
5880                 {
5881                         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);
5882                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5883                 }
5884                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5885                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5886                 if (mode == SHADERMODE_LIGHTSOURCE)
5887                 {
5888                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5889                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5890                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5891                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5892                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5893                         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);
5894         
5895                         // additive passes are only darkened by fog, not tinted
5896                         if (r_glsl_permutation->loc_FogColor >= 0)
5897                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5898                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5899                 }
5900                 else
5901                 {
5902                         if (mode == SHADERMODE_FLATCOLOR)
5903                         {
5904                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5905                         }
5906                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5907                         {
5908                                 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]);
5909                                 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]);
5910                                 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);
5911                                 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);
5912                                 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);
5913                                 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]);
5914                                 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]);
5915                         }
5916                         else
5917                         {
5918                                 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]);
5919                                 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]);
5920                                 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);
5921                                 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);
5922                                 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);
5923                         }
5924                         // additive passes are only darkened by fog, not tinted
5925                         if (r_glsl_permutation->loc_FogColor >= 0)
5926                         {
5927                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5928                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5929                                 else
5930                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5931                         }
5932                         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);
5933                         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]);
5934                         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]);
5935                         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]);
5936                         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]);
5937                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5938                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5939                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5940                         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]);
5941                 }
5942                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5943                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5944                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5945                 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]);
5946                 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]);
5947
5948                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5949                 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));
5950                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5951                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5952                 {
5953                         if (rsurface.texture->pantstexture)
5954                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5955                         else
5956                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5957                 }
5958                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5959                 {
5960                         if (rsurface.texture->shirttexture)
5961                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5962                         else
5963                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5964                 }
5965                 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]);
5966                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5967                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5968                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5969                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5970                 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]);
5971                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5972
5973                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
5974                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
5975                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
5976                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
5977                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
5978                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
5979                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
5980                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
5981                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
5982                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
5983                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
5984                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
5985                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
5986                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
5987                 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);
5988                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
5989                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
5990                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5991                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5992                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
5993                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5994                 {
5995                         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);
5996                         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);
5997                         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);
5998                 }
5999                 else
6000                 {
6001                         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);
6002                 }
6003                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
6004                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
6005                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
6006                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
6007                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6008                 {
6009                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
6010                         if (rsurface.rtlight)
6011                         {
6012                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
6013                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
6014                         }
6015                 }
6016                 CHECKGLERROR
6017                 break;
6018         case RENDERPATH_CGGL:
6019 #ifdef SUPPORTCG
6020                 if (!vid.useinterleavedarrays)
6021                 {
6022                         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);
6023                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
6024                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
6025                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
6026                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
6027                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6028                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6029                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6030                 }
6031                 else
6032                 {
6033                         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);
6034                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6035                 }
6036                 R_SetupShader_SetPermutationCG(mode, permutation);
6037                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6038                 if (mode == SHADERMODE_LIGHTSOURCE)
6039                 {
6040                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6041                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6042                 }
6043                 else
6044                 {
6045                         if (mode == SHADERMODE_LIGHTDIRECTION)
6046                         {
6047                                 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
6048                         }
6049                 }
6050                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6051                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6052                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6053                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6054                 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
6055                 CHECKGLERROR
6056
6057                 if (mode == SHADERMODE_LIGHTSOURCE)
6058                 {
6059                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6060                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6061                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6062                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6063                         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
6064
6065                         // additive passes are only darkened by fog, not tinted
6066                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6067                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6068                 }
6069                 else
6070                 {
6071                         if (mode == SHADERMODE_FLATCOLOR)
6072                         {
6073                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6074                         }
6075                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6076                         {
6077                                 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
6078                                 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
6079                                 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
6080                                 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
6081                                 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
6082                                 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
6083                                 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
6084                         }
6085                         else
6086                         {
6087                                 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
6088                                 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
6089                                 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
6090                                 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
6091                                 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
6092                         }
6093                         // additive passes are only darkened by fog, not tinted
6094                         if (r_cg_permutation->fp_FogColor)
6095                         {
6096                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6097                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6098                                 else
6099                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6100                                 CHECKCGERROR
6101                         }
6102                         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
6103                         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
6104                         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
6105                         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
6106                         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
6107                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6108                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6109                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6110                         if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6111                 }
6112                 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
6113                 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
6114                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6115                 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
6116                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6117                 if (r_cg_permutation->fp_Color_Pants)
6118                 {
6119                         if (rsurface.texture->pantstexture)
6120                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6121                         else
6122                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6123                         CHECKCGERROR
6124                 }
6125                 if (r_cg_permutation->fp_Color_Shirt)
6126                 {
6127                         if (rsurface.texture->shirttexture)
6128                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6129                         else
6130                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6131                         CHECKCGERROR
6132                 }
6133                 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
6134                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6135                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6136                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6137                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6138                 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
6139                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6140
6141         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
6142         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
6143         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
6144                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
6145                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
6146                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
6147                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
6148                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
6149                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
6150                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
6151                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
6152                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
6153                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
6154                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
6155                 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
6156                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
6157                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
6158                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6159                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6160                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6161                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6162                 {
6163                         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
6164                         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
6165                         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
6166                 }
6167                 else
6168                 {
6169                         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
6170                 }
6171                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6172                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6173                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6174                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6175                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6176                 {
6177                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6178                         if (rsurface.rtlight)
6179                         {
6180                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6181                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6182                         }
6183                 }
6184
6185                 CHECKGLERROR
6186 #endif
6187                 break;
6188         case RENDERPATH_GL13:
6189         case RENDERPATH_GL11:
6190                 break;
6191         case RENDERPATH_SOFT:
6192                 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);
6193                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
6194                 R_SetupShader_SetPermutationSoft(mode, permutation);
6195                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
6196                 if (mode == SHADERMODE_LIGHTSOURCE)
6197                 {
6198                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
6199                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
6200                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
6201                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
6202                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
6203                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
6204         
6205                         // additive passes are only darkened by fog, not tinted
6206                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
6207                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6208                 }
6209                 else
6210                 {
6211                         if (mode == SHADERMODE_FLATCOLOR)
6212                         {
6213                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
6214                         }
6215                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6216                         {
6217                                 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]);
6218                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
6219                                 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);
6220                                 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);
6221                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
6222                                 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]);
6223                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
6224                         }
6225                         else
6226                         {
6227                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
6228                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
6229                                 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);
6230                                 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);
6231                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
6232                         }
6233                         // additive passes are only darkened by fog, not tinted
6234                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6235                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
6236                         else
6237                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6238                         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);
6239                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
6240                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
6241                         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]);
6242                         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]);
6243                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
6244                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
6245                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6246                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6247                 }
6248                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
6249                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
6250                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
6251                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6252                 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]);
6253
6254                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
6255                 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));
6256                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
6257                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
6258                 {
6259                         if (rsurface.texture->pantstexture)
6260                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6261                         else
6262                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
6263                 }
6264                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
6265                 {
6266                         if (rsurface.texture->shirttexture)
6267                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6268                         else
6269                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
6270                 }
6271                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
6272                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
6273                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
6274                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
6275                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
6276                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6277                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6278
6279                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
6280                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
6281                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
6282                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
6283                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
6284                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
6285                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
6286                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
6287                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
6288                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
6289                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
6290                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
6291                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
6292                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
6293                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
6294                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
6295                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
6296                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6297                 {
6298                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
6299                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
6300                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6301                 }
6302                 else
6303                 {
6304                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6305                 }
6306 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
6307 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
6308                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
6309                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
6310                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6311                 {
6312                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
6313                         if (rsurface.rtlight)
6314                         {
6315                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
6316                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
6317                         }
6318                 }
6319                 break;
6320         }
6321 }
6322
6323 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6324 {
6325         // select a permutation of the lighting shader appropriate to this
6326         // combination of texture, entity, light source, and fogging, only use the
6327         // minimum features necessary to avoid wasting rendering time in the
6328         // fragment shader on features that are not being used
6329         unsigned int permutation = 0;
6330         unsigned int mode = 0;
6331         const float *lightcolorbase = rtlight->currentcolor;
6332         float ambientscale = rtlight->ambientscale;
6333         float diffusescale = rtlight->diffusescale;
6334         float specularscale = rtlight->specularscale;
6335         // this is the location of the light in view space
6336         vec3_t viewlightorigin;
6337         // this transforms from view space (camera) to light space (cubemap)
6338         matrix4x4_t viewtolight;
6339         matrix4x4_t lighttoview;
6340         float viewtolight16f[16];
6341         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6342         // light source
6343         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6344         if (rtlight->currentcubemap != r_texture_whitecube)
6345                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6346         if (diffusescale > 0)
6347                 permutation |= SHADERPERMUTATION_DIFFUSE;
6348         if (specularscale > 0)
6349                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6350         if (r_shadow_usingshadowmap2d)
6351         {
6352                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6353                 if (r_shadow_shadowmapvsdct)
6354                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6355
6356                 if (r_shadow_shadowmapsampler)
6357                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6358                 if (r_shadow_shadowmappcf > 1)
6359                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6360                 else if (r_shadow_shadowmappcf)
6361                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6362         }
6363         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6364         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6365         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6366         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6367         switch(vid.renderpath)
6368         {
6369         case RENDERPATH_D3D9:
6370 #ifdef SUPPORTD3D
6371                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6372                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6373                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6374                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6375                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6376                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6377                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6378                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6379                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6380                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6381                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6382
6383                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6384                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
6385                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6386                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6387                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
6388                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6389 #endif
6390                 break;
6391         case RENDERPATH_D3D10:
6392                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6393                 break;
6394         case RENDERPATH_D3D11:
6395                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6396                 break;
6397         case RENDERPATH_GL20:
6398         case RENDERPATH_GLES2:
6399                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6400                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6401                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6402                 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);
6403                 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);
6404                 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);
6405                 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]);
6406                 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]);
6407                 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));
6408                 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]);
6409                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
6410
6411                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
6412                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
6413                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
6414                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
6415                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
6416                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
6417                 break;
6418         case RENDERPATH_CGGL:
6419 #ifdef SUPPORTCG
6420                 R_SetupShader_SetPermutationCG(mode, permutation);
6421                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6422                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6423                 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
6424                 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
6425                 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
6426                 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
6427                 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
6428                 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
6429                 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
6430                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6431
6432                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6433                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6434                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6435                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6436                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6437                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6438 #endif
6439                 break;
6440         case RENDERPATH_GL13:
6441         case RENDERPATH_GL11:
6442                 break;
6443         case RENDERPATH_SOFT:
6444                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6445                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6446                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
6447                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6448                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6449                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6450                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6451                 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]);
6452                 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));
6453                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6454                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6455
6456                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6457                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6458                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6459                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6460                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6461                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6462                 break;
6463         }
6464 }
6465
6466 #define SKINFRAME_HASH 1024
6467
6468 typedef struct
6469 {
6470         int loadsequence; // incremented each level change
6471         memexpandablearray_t array;
6472         skinframe_t *hash[SKINFRAME_HASH];
6473 }
6474 r_skinframe_t;
6475 r_skinframe_t r_skinframe;
6476
6477 void R_SkinFrame_PrepareForPurge(void)
6478 {
6479         r_skinframe.loadsequence++;
6480         // wrap it without hitting zero
6481         if (r_skinframe.loadsequence >= 200)
6482                 r_skinframe.loadsequence = 1;
6483 }
6484
6485 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6486 {
6487         if (!skinframe)
6488                 return;
6489         // mark the skinframe as used for the purging code
6490         skinframe->loadsequence = r_skinframe.loadsequence;
6491 }
6492
6493 void R_SkinFrame_Purge(void)
6494 {
6495         int i;
6496         skinframe_t *s;
6497         for (i = 0;i < SKINFRAME_HASH;i++)
6498         {
6499                 for (s = r_skinframe.hash[i];s;s = s->next)
6500                 {
6501                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6502                         {
6503                                 if (s->merged == s->base)
6504                                         s->merged = NULL;
6505                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6506                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6507                                 R_PurgeTexture(s->merged);s->merged = NULL;
6508                                 R_PurgeTexture(s->base  );s->base   = NULL;
6509                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6510                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6511                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6512                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6513                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6514                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6515                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6516                                 s->loadsequence = 0;
6517                         }
6518                 }
6519         }
6520 }
6521
6522 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6523         skinframe_t *item;
6524         char basename[MAX_QPATH];
6525
6526         Image_StripImageExtension(name, basename, sizeof(basename));
6527
6528         if( last == NULL ) {
6529                 int hashindex;
6530                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6531                 item = r_skinframe.hash[hashindex];
6532         } else {
6533                 item = last->next;
6534         }
6535
6536         // linearly search through the hash bucket
6537         for( ; item ; item = item->next ) {
6538                 if( !strcmp( item->basename, basename ) ) {
6539                         return item;
6540                 }
6541         }
6542         return NULL;
6543 }
6544
6545 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6546 {
6547         skinframe_t *item;
6548         int hashindex;
6549         char basename[MAX_QPATH];
6550
6551         Image_StripImageExtension(name, basename, sizeof(basename));
6552
6553         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6554         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6555                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6556                         break;
6557
6558         if (!item) {
6559                 rtexture_t *dyntexture;
6560                 // check whether its a dynamic texture
6561                 dyntexture = CL_GetDynTexture( basename );
6562                 if (!add && !dyntexture)
6563                         return NULL;
6564                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6565                 memset(item, 0, sizeof(*item));
6566                 strlcpy(item->basename, basename, sizeof(item->basename));
6567                 item->base = dyntexture; // either NULL or dyntexture handle
6568                 item->textureflags = textureflags;
6569                 item->comparewidth = comparewidth;
6570                 item->compareheight = compareheight;
6571                 item->comparecrc = comparecrc;
6572                 item->next = r_skinframe.hash[hashindex];
6573                 r_skinframe.hash[hashindex] = item;
6574         }
6575         else if( item->base == NULL )
6576         {
6577                 rtexture_t *dyntexture;
6578                 // check whether its a dynamic texture
6579                 // 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]
6580                 dyntexture = CL_GetDynTexture( basename );
6581                 item->base = dyntexture; // either NULL or dyntexture handle
6582         }
6583
6584         R_SkinFrame_MarkUsed(item);
6585         return item;
6586 }
6587
6588 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6589         { \
6590                 unsigned long long avgcolor[5], wsum; \
6591                 int pix, comp, w; \
6592                 avgcolor[0] = 0; \
6593                 avgcolor[1] = 0; \
6594                 avgcolor[2] = 0; \
6595                 avgcolor[3] = 0; \
6596                 avgcolor[4] = 0; \
6597                 wsum = 0; \
6598                 for(pix = 0; pix < cnt; ++pix) \
6599                 { \
6600                         w = 0; \
6601                         for(comp = 0; comp < 3; ++comp) \
6602                                 w += getpixel; \
6603                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6604                         { \
6605                                 ++wsum; \
6606                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6607                                 w = getpixel; \
6608                                 for(comp = 0; comp < 3; ++comp) \
6609                                         avgcolor[comp] += getpixel * w; \
6610                                 avgcolor[3] += w; \
6611                         } \
6612                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6613                         avgcolor[4] += getpixel; \
6614                 } \
6615                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6616                         avgcolor[3] = 1; \
6617                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6618                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6619                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6620                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6621         }
6622
6623 extern cvar_t gl_picmip;
6624 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6625 {
6626         int j;
6627         unsigned char *pixels;
6628         unsigned char *bumppixels;
6629         unsigned char *basepixels = NULL;
6630         int basepixels_width = 0;
6631         int basepixels_height = 0;
6632         skinframe_t *skinframe;
6633         rtexture_t *ddsbase = NULL;
6634         qboolean ddshasalpha = false;
6635         float ddsavgcolor[4];
6636         char basename[MAX_QPATH];
6637         int miplevel = R_PicmipForFlags(textureflags);
6638         int savemiplevel = miplevel;
6639         int mymiplevel;
6640
6641         if (cls.state == ca_dedicated)
6642                 return NULL;
6643
6644         // return an existing skinframe if already loaded
6645         // if loading of the first image fails, don't make a new skinframe as it
6646         // would cause all future lookups of this to be missing
6647         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6648         if (skinframe && skinframe->base)
6649                 return skinframe;
6650
6651         Image_StripImageExtension(name, basename, sizeof(basename));
6652
6653         // check for DDS texture file first
6654         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6655         {
6656                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6657                 if (basepixels == NULL)
6658                         return NULL;
6659         }
6660
6661         // FIXME handle miplevel
6662
6663         if (developer_loading.integer)
6664                 Con_Printf("loading skin \"%s\"\n", name);
6665
6666         // we've got some pixels to store, so really allocate this new texture now
6667         if (!skinframe)
6668                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6669         skinframe->stain = NULL;
6670         skinframe->merged = NULL;
6671         skinframe->base = NULL;
6672         skinframe->pants = NULL;
6673         skinframe->shirt = NULL;
6674         skinframe->nmap = NULL;
6675         skinframe->gloss = NULL;
6676         skinframe->glow = NULL;
6677         skinframe->fog = NULL;
6678         skinframe->reflect = NULL;
6679         skinframe->hasalpha = false;
6680
6681         if (ddsbase)
6682         {
6683                 skinframe->base = ddsbase;
6684                 skinframe->hasalpha = ddshasalpha;
6685                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6686                 if (r_loadfog && skinframe->hasalpha)
6687                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6688                 //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]);
6689         }
6690         else
6691         {
6692                 basepixels_width = image_width;
6693                 basepixels_height = image_height;
6694                 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);
6695                 if (textureflags & TEXF_ALPHA)
6696                 {
6697                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6698                         {
6699                                 if (basepixels[j] < 255)
6700                                 {
6701                                         skinframe->hasalpha = true;
6702                                         break;
6703                                 }
6704                         }
6705                         if (r_loadfog && skinframe->hasalpha)
6706                         {
6707                                 // has transparent pixels
6708                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6709                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6710                                 {
6711                                         pixels[j+0] = 255;
6712                                         pixels[j+1] = 255;
6713                                         pixels[j+2] = 255;
6714                                         pixels[j+3] = basepixels[j+3];
6715                                 }
6716                                 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);
6717                                 Mem_Free(pixels);
6718                         }
6719                 }
6720                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6721                 //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]);
6722                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6723                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6724                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6725                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6726         }
6727
6728         if (r_loaddds)
6729         {
6730                 mymiplevel = savemiplevel;
6731                 if (r_loadnormalmap)
6732                         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);
6733                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6734                 if (r_loadgloss)
6735                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6736                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6737                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6738                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6739         }
6740
6741         // _norm is the name used by tenebrae and has been adopted as standard
6742         if (r_loadnormalmap && skinframe->nmap == NULL)
6743         {
6744                 mymiplevel = savemiplevel;
6745                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6746                 {
6747                         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);
6748                         Mem_Free(pixels);
6749                         pixels = NULL;
6750                 }
6751                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6752                 {
6753                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6754                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6755                         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);
6756                         Mem_Free(pixels);
6757                         Mem_Free(bumppixels);
6758                 }
6759                 else if (r_shadow_bumpscale_basetexture.value > 0)
6760                 {
6761                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6762                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6763                         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);
6764                         Mem_Free(pixels);
6765                 }
6766                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6767                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6768         }
6769
6770         // _luma is supported only for tenebrae compatibility
6771         // _glow is the preferred name
6772         mymiplevel = savemiplevel;
6773         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))))
6774         {
6775                 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);
6776                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6777                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6778                 Mem_Free(pixels);pixels = NULL;
6779         }
6780
6781         mymiplevel = savemiplevel;
6782         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6783         {
6784                 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);
6785                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6786                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6787                 Mem_Free(pixels);
6788                 pixels = NULL;
6789         }
6790
6791         mymiplevel = savemiplevel;
6792         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6793         {
6794                 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);
6795                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6796                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6797                 Mem_Free(pixels);
6798                 pixels = NULL;
6799         }
6800
6801         mymiplevel = savemiplevel;
6802         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6803         {
6804                 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);
6805                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6806                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6807                 Mem_Free(pixels);
6808                 pixels = NULL;
6809         }
6810
6811         mymiplevel = savemiplevel;
6812         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6813         {
6814                 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);
6815                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6816                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6817                 Mem_Free(pixels);
6818                 pixels = NULL;
6819         }
6820
6821         if (basepixels)
6822                 Mem_Free(basepixels);
6823
6824         return skinframe;
6825 }
6826
6827 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6828 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6829 {
6830         int i;
6831         unsigned char *temp1, *temp2;
6832         skinframe_t *skinframe;
6833
6834         if (cls.state == ca_dedicated)
6835                 return NULL;
6836
6837         // if already loaded just return it, otherwise make a new skinframe
6838         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6839         if (skinframe && skinframe->base)
6840                 return skinframe;
6841
6842         skinframe->stain = NULL;
6843         skinframe->merged = NULL;
6844         skinframe->base = NULL;
6845         skinframe->pants = NULL;
6846         skinframe->shirt = NULL;
6847         skinframe->nmap = NULL;
6848         skinframe->gloss = NULL;
6849         skinframe->glow = NULL;
6850         skinframe->fog = NULL;
6851         skinframe->reflect = NULL;
6852         skinframe->hasalpha = false;
6853
6854         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6855         if (!skindata)
6856                 return NULL;
6857
6858         if (developer_loading.integer)
6859                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6860
6861         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6862         {
6863                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6864                 temp2 = temp1 + width * height * 4;
6865                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6866                 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);
6867                 Mem_Free(temp1);
6868         }
6869         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6870         if (textureflags & TEXF_ALPHA)
6871         {
6872                 for (i = 3;i < width * height * 4;i += 4)
6873                 {
6874                         if (skindata[i] < 255)
6875                         {
6876                                 skinframe->hasalpha = true;
6877                                 break;
6878                         }
6879                 }
6880                 if (r_loadfog && skinframe->hasalpha)
6881                 {
6882                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6883                         memcpy(fogpixels, skindata, width * height * 4);
6884                         for (i = 0;i < width * height * 4;i += 4)
6885                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6886                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6887                         Mem_Free(fogpixels);
6888                 }
6889         }
6890
6891         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6892         //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]);
6893
6894         return skinframe;
6895 }
6896
6897 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6898 {
6899         int i;
6900         int featuresmask;
6901         skinframe_t *skinframe;
6902
6903         if (cls.state == ca_dedicated)
6904                 return NULL;
6905
6906         // if already loaded just return it, otherwise make a new skinframe
6907         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6908         if (skinframe && skinframe->base)
6909                 return skinframe;
6910
6911         skinframe->stain = NULL;
6912         skinframe->merged = NULL;
6913         skinframe->base = NULL;
6914         skinframe->pants = NULL;
6915         skinframe->shirt = NULL;
6916         skinframe->nmap = NULL;
6917         skinframe->gloss = NULL;
6918         skinframe->glow = NULL;
6919         skinframe->fog = NULL;
6920         skinframe->reflect = NULL;
6921         skinframe->hasalpha = false;
6922
6923         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6924         if (!skindata)
6925                 return NULL;
6926
6927         if (developer_loading.integer)
6928                 Con_Printf("loading quake skin \"%s\"\n", name);
6929
6930         // 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)
6931         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6932         memcpy(skinframe->qpixels, skindata, width*height);
6933         skinframe->qwidth = width;
6934         skinframe->qheight = height;
6935
6936         featuresmask = 0;
6937         for (i = 0;i < width * height;i++)
6938                 featuresmask |= palette_featureflags[skindata[i]];
6939
6940         skinframe->hasalpha = false;
6941         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6942         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6943         skinframe->qgeneratemerged = true;
6944         skinframe->qgeneratebase = skinframe->qhascolormapping;
6945         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6946
6947         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6948         //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]);
6949
6950         return skinframe;
6951 }
6952
6953 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6954 {
6955         int width;
6956         int height;
6957         unsigned char *skindata;
6958
6959         if (!skinframe->qpixels)
6960                 return;
6961
6962         if (!skinframe->qhascolormapping)
6963                 colormapped = false;
6964
6965         if (colormapped)
6966         {
6967                 if (!skinframe->qgeneratebase)
6968                         return;
6969         }
6970         else
6971         {
6972                 if (!skinframe->qgeneratemerged)
6973                         return;
6974         }
6975
6976         width = skinframe->qwidth;
6977         height = skinframe->qheight;
6978         skindata = skinframe->qpixels;
6979
6980         if (skinframe->qgeneratenmap)
6981         {
6982                 unsigned char *temp1, *temp2;
6983                 skinframe->qgeneratenmap = false;
6984                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6985                 temp2 = temp1 + width * height * 4;
6986                 // use either a custom palette or the quake palette
6987                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6988                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6989                 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);
6990                 Mem_Free(temp1);
6991         }
6992
6993         if (skinframe->qgenerateglow)
6994         {
6995                 skinframe->qgenerateglow = false;
6996                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6997         }
6998
6999         if (colormapped)
7000         {
7001                 skinframe->qgeneratebase = false;
7002                 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);
7003                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
7004                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
7005         }
7006         else
7007         {
7008                 skinframe->qgeneratemerged = false;
7009                 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);
7010         }
7011
7012         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
7013         {
7014                 Mem_Free(skinframe->qpixels);
7015                 skinframe->qpixels = NULL;
7016         }
7017 }
7018
7019 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)
7020 {
7021         int i;
7022         skinframe_t *skinframe;
7023
7024         if (cls.state == ca_dedicated)
7025                 return NULL;
7026
7027         // if already loaded just return it, otherwise make a new skinframe
7028         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
7029         if (skinframe && skinframe->base)
7030                 return skinframe;
7031
7032         skinframe->stain = NULL;
7033         skinframe->merged = NULL;
7034         skinframe->base = NULL;
7035         skinframe->pants = NULL;
7036         skinframe->shirt = NULL;
7037         skinframe->nmap = NULL;
7038         skinframe->gloss = NULL;
7039         skinframe->glow = NULL;
7040         skinframe->fog = NULL;
7041         skinframe->reflect = NULL;
7042         skinframe->hasalpha = false;
7043
7044         // if no data was provided, then clearly the caller wanted to get a blank skinframe
7045         if (!skindata)
7046                 return NULL;
7047
7048         if (developer_loading.integer)
7049                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
7050
7051         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
7052         if (textureflags & TEXF_ALPHA)
7053         {
7054                 for (i = 0;i < width * height;i++)
7055                 {
7056                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
7057                         {
7058                                 skinframe->hasalpha = true;
7059                                 break;
7060                         }
7061                 }
7062                 if (r_loadfog && skinframe->hasalpha)
7063                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
7064         }
7065
7066         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
7067         //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]);
7068
7069         return skinframe;
7070 }
7071
7072 skinframe_t *R_SkinFrame_LoadMissing(void)
7073 {
7074         skinframe_t *skinframe;
7075
7076         if (cls.state == ca_dedicated)
7077                 return NULL;
7078
7079         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
7080         skinframe->stain = NULL;
7081         skinframe->merged = NULL;
7082         skinframe->base = NULL;
7083         skinframe->pants = NULL;
7084         skinframe->shirt = NULL;
7085         skinframe->nmap = NULL;
7086         skinframe->gloss = NULL;
7087         skinframe->glow = NULL;
7088         skinframe->fog = NULL;
7089         skinframe->reflect = NULL;
7090         skinframe->hasalpha = false;
7091
7092         skinframe->avgcolor[0] = rand() / RAND_MAX;
7093         skinframe->avgcolor[1] = rand() / RAND_MAX;
7094         skinframe->avgcolor[2] = rand() / RAND_MAX;
7095         skinframe->avgcolor[3] = 1;
7096
7097         return skinframe;
7098 }
7099
7100 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
7101 typedef struct suffixinfo_s
7102 {
7103         const char *suffix;
7104         qboolean flipx, flipy, flipdiagonal;
7105 }
7106 suffixinfo_t;
7107 static suffixinfo_t suffix[3][6] =
7108 {
7109         {
7110                 {"px",   false, false, false},
7111                 {"nx",   false, false, false},
7112                 {"py",   false, false, false},
7113                 {"ny",   false, false, false},
7114                 {"pz",   false, false, false},
7115                 {"nz",   false, false, false}
7116         },
7117         {
7118                 {"posx", false, false, false},
7119                 {"negx", false, false, false},
7120                 {"posy", false, false, false},
7121                 {"negy", false, false, false},
7122                 {"posz", false, false, false},
7123                 {"negz", false, false, false}
7124         },
7125         {
7126                 {"rt",    true, false,  true},
7127                 {"lf",   false,  true,  true},
7128                 {"ft",    true,  true, false},
7129                 {"bk",   false, false, false},
7130                 {"up",    true, false,  true},
7131                 {"dn",    true, false,  true}
7132         }
7133 };
7134
7135 static int componentorder[4] = {0, 1, 2, 3};
7136
7137 rtexture_t *R_LoadCubemap(const char *basename)
7138 {
7139         int i, j, cubemapsize;
7140         unsigned char *cubemappixels, *image_buffer;
7141         rtexture_t *cubemaptexture;
7142         char name[256];
7143         // must start 0 so the first loadimagepixels has no requested width/height
7144         cubemapsize = 0;
7145         cubemappixels = NULL;
7146         cubemaptexture = NULL;
7147         // keep trying different suffix groups (posx, px, rt) until one loads
7148         for (j = 0;j < 3 && !cubemappixels;j++)
7149         {
7150                 // load the 6 images in the suffix group
7151                 for (i = 0;i < 6;i++)
7152                 {
7153                         // generate an image name based on the base and and suffix
7154                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
7155                         // load it
7156                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
7157                         {
7158                                 // an image loaded, make sure width and height are equal
7159                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
7160                                 {
7161                                         // if this is the first image to load successfully, allocate the cubemap memory
7162                                         if (!cubemappixels && image_width >= 1)
7163                                         {
7164                                                 cubemapsize = image_width;
7165                                                 // note this clears to black, so unavailable sides are black
7166                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7167                                         }
7168                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7169                                         if (cubemappixels)
7170                                                 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);
7171                                 }
7172                                 else
7173                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7174                                 // free the image
7175                                 Mem_Free(image_buffer);
7176                         }
7177                 }
7178         }
7179         // if a cubemap loaded, upload it
7180         if (cubemappixels)
7181         {
7182                 if (developer_loading.integer)
7183                         Con_Printf("loading cubemap \"%s\"\n", basename);
7184
7185                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7186                 Mem_Free(cubemappixels);
7187         }
7188         else
7189         {
7190                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7191                 if (developer_loading.integer)
7192                 {
7193                         Con_Printf("(tried tried images ");
7194                         for (j = 0;j < 3;j++)
7195                                 for (i = 0;i < 6;i++)
7196                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7197                         Con_Print(" and was unable to find any of them).\n");
7198                 }
7199         }
7200         return cubemaptexture;
7201 }
7202
7203 rtexture_t *R_GetCubemap(const char *basename)
7204 {
7205         int i;
7206         for (i = 0;i < r_texture_numcubemaps;i++)
7207                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7208                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7209         if (i >= MAX_CUBEMAPS)
7210                 return r_texture_whitecube;
7211         r_texture_numcubemaps++;
7212         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7213         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7214         return r_texture_cubemaps[i].texture;
7215 }
7216
7217 void R_FreeCubemaps(void)
7218 {
7219         int i;
7220         for (i = 0;i < r_texture_numcubemaps;i++)
7221         {
7222                 if (developer_loading.integer)
7223                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7224                 if (r_texture_cubemaps[i].texture)
7225                         R_FreeTexture(r_texture_cubemaps[i].texture);
7226         }
7227         r_texture_numcubemaps = 0;
7228 }
7229
7230 void R_Main_FreeViewCache(void)
7231 {
7232         if (r_refdef.viewcache.entityvisible)
7233                 Mem_Free(r_refdef.viewcache.entityvisible);
7234         if (r_refdef.viewcache.world_pvsbits)
7235                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7236         if (r_refdef.viewcache.world_leafvisible)
7237                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7238         if (r_refdef.viewcache.world_surfacevisible)
7239                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7240         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7241 }
7242
7243 void R_Main_ResizeViewCache(void)
7244 {
7245         int numentities = r_refdef.scene.numentities;
7246         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7247         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7248         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7249         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7250         if (r_refdef.viewcache.maxentities < numentities)
7251         {
7252                 r_refdef.viewcache.maxentities = numentities;
7253                 if (r_refdef.viewcache.entityvisible)
7254                         Mem_Free(r_refdef.viewcache.entityvisible);
7255                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7256         }
7257         if (r_refdef.viewcache.world_numclusters != numclusters)
7258         {
7259                 r_refdef.viewcache.world_numclusters = numclusters;
7260                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7261                 if (r_refdef.viewcache.world_pvsbits)
7262                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7263                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7264         }
7265         if (r_refdef.viewcache.world_numleafs != numleafs)
7266         {
7267                 r_refdef.viewcache.world_numleafs = numleafs;
7268                 if (r_refdef.viewcache.world_leafvisible)
7269                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7270                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7271         }
7272         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7273         {
7274                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7275                 if (r_refdef.viewcache.world_surfacevisible)
7276                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7277                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7278         }
7279 }
7280
7281 extern rtexture_t *loadingscreentexture;
7282 void gl_main_start(void)
7283 {
7284         loadingscreentexture = NULL;
7285         r_texture_blanknormalmap = NULL;
7286         r_texture_white = NULL;
7287         r_texture_grey128 = NULL;
7288         r_texture_black = NULL;
7289         r_texture_whitecube = NULL;
7290         r_texture_normalizationcube = NULL;
7291         r_texture_fogattenuation = NULL;
7292         r_texture_fogheighttexture = NULL;
7293         r_texture_gammaramps = NULL;
7294         r_texture_numcubemaps = 0;
7295
7296         r_loaddds = r_texture_dds_load.integer != 0;
7297         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7298
7299         switch(vid.renderpath)
7300         {
7301         case RENDERPATH_GL20:
7302         case RENDERPATH_CGGL:
7303         case RENDERPATH_D3D9:
7304         case RENDERPATH_D3D10:
7305         case RENDERPATH_D3D11:
7306         case RENDERPATH_SOFT:
7307                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7308                 Cvar_SetValueQuick(&gl_combine, 1);
7309                 Cvar_SetValueQuick(&r_glsl, 1);
7310                 r_loadnormalmap = true;
7311                 r_loadgloss = true;
7312                 r_loadfog = false;
7313                 break;
7314         case RENDERPATH_GL13:
7315                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7316                 Cvar_SetValueQuick(&gl_combine, 1);
7317                 Cvar_SetValueQuick(&r_glsl, 0);
7318                 r_loadnormalmap = false;
7319                 r_loadgloss = false;
7320                 r_loadfog = true;
7321                 break;
7322         case RENDERPATH_GL11:
7323                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7324                 Cvar_SetValueQuick(&gl_combine, 0);
7325                 Cvar_SetValueQuick(&r_glsl, 0);
7326                 r_loadnormalmap = false;
7327                 r_loadgloss = false;
7328                 r_loadfog = true;
7329                 break;
7330         case RENDERPATH_GLES2:
7331                 Cvar_SetValueQuick(&r_textureunits, 1);
7332                 Cvar_SetValueQuick(&gl_combine, 1);
7333                 Cvar_SetValueQuick(&r_glsl, 1);
7334                 r_loadnormalmap = true;
7335                 r_loadgloss = false;
7336                 r_loadfog = false;
7337                 break;
7338         }
7339
7340         R_AnimCache_Free();
7341         R_FrameData_Reset();
7342
7343         r_numqueries = 0;
7344         r_maxqueries = 0;
7345         memset(r_queries, 0, sizeof(r_queries));
7346
7347         r_qwskincache = NULL;
7348         r_qwskincache_size = 0;
7349
7350         // set up r_skinframe loading system for textures
7351         memset(&r_skinframe, 0, sizeof(r_skinframe));
7352         r_skinframe.loadsequence = 1;
7353         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7354
7355         r_main_texturepool = R_AllocTexturePool();
7356         R_BuildBlankTextures();
7357         R_BuildNoTexture();
7358         if (vid.support.arb_texture_cube_map)
7359         {
7360                 R_BuildWhiteCube();
7361                 R_BuildNormalizationCube();
7362         }
7363         r_texture_fogattenuation = NULL;
7364         r_texture_fogheighttexture = NULL;
7365         r_texture_gammaramps = NULL;
7366         //r_texture_fogintensity = NULL;
7367         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7368         memset(&r_waterstate, 0, sizeof(r_waterstate));
7369         r_glsl_permutation = NULL;
7370         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7371         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7372         glslshaderstring = NULL;
7373 #ifdef SUPPORTCG
7374         r_cg_permutation = NULL;
7375         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7376         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7377 #endif
7378 #ifdef SUPPORTD3D
7379         r_hlsl_permutation = NULL;
7380         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7381         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7382 #endif
7383         hlslshaderstring = NULL;
7384         memset(&r_svbsp, 0, sizeof (r_svbsp));
7385
7386         r_refdef.fogmasktable_density = 0;
7387 }
7388
7389 void gl_main_shutdown(void)
7390 {
7391         R_AnimCache_Free();
7392         R_FrameData_Reset();
7393
7394         R_Main_FreeViewCache();
7395
7396         switch(vid.renderpath)
7397         {
7398         case RENDERPATH_GL11:
7399         case RENDERPATH_GL13:
7400         case RENDERPATH_GL20:
7401         case RENDERPATH_CGGL:
7402         case RENDERPATH_GLES2:
7403                 if (r_maxqueries)
7404                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7405                 break;
7406         case RENDERPATH_D3D9:
7407                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7408                 break;
7409         case RENDERPATH_D3D10:
7410                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7411                 break;
7412         case RENDERPATH_D3D11:
7413                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7414                 break;
7415         case RENDERPATH_SOFT:
7416                 break;
7417         }
7418
7419         r_numqueries = 0;
7420         r_maxqueries = 0;
7421         memset(r_queries, 0, sizeof(r_queries));
7422
7423         r_qwskincache = NULL;
7424         r_qwskincache_size = 0;
7425
7426         // clear out the r_skinframe state
7427         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7428         memset(&r_skinframe, 0, sizeof(r_skinframe));
7429
7430         if (r_svbsp.nodes)
7431                 Mem_Free(r_svbsp.nodes);
7432         memset(&r_svbsp, 0, sizeof (r_svbsp));
7433         R_FreeTexturePool(&r_main_texturepool);
7434         loadingscreentexture = NULL;
7435         r_texture_blanknormalmap = NULL;
7436         r_texture_white = NULL;
7437         r_texture_grey128 = NULL;
7438         r_texture_black = NULL;
7439         r_texture_whitecube = NULL;
7440         r_texture_normalizationcube = NULL;
7441         r_texture_fogattenuation = NULL;
7442         r_texture_fogheighttexture = NULL;
7443         r_texture_gammaramps = NULL;
7444         r_texture_numcubemaps = 0;
7445         //r_texture_fogintensity = NULL;
7446         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7447         memset(&r_waterstate, 0, sizeof(r_waterstate));
7448         R_GLSL_Restart_f();
7449
7450         r_glsl_permutation = NULL;
7451         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7452         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
7453         glslshaderstring = NULL;
7454 #ifdef SUPPORTCG
7455         r_cg_permutation = NULL;
7456         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7457         Mem_ExpandableArray_FreeArray(&r_cg_permutationarray);
7458 #endif
7459 #ifdef SUPPORTD3D
7460         r_hlsl_permutation = NULL;
7461         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7462         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
7463 #endif
7464         hlslshaderstring = NULL;
7465 }
7466
7467 extern void CL_ParseEntityLump(char *entitystring);
7468 void gl_main_newmap(void)
7469 {
7470         // FIXME: move this code to client
7471         char *entities, entname[MAX_QPATH];
7472         if (r_qwskincache)
7473                 Mem_Free(r_qwskincache);
7474         r_qwskincache = NULL;
7475         r_qwskincache_size = 0;
7476         if (cl.worldmodel)
7477         {
7478                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7479                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7480                 {
7481                         CL_ParseEntityLump(entities);
7482                         Mem_Free(entities);
7483                         return;
7484                 }
7485                 if (cl.worldmodel->brush.entities)
7486                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7487         }
7488         R_Main_FreeViewCache();
7489
7490         R_FrameData_Reset();
7491 }
7492
7493 void GL_Main_Init(void)
7494 {
7495         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7496
7497         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7498         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7499         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7500         if (gamemode == GAME_NEHAHRA)
7501         {
7502                 Cvar_RegisterVariable (&gl_fogenable);
7503                 Cvar_RegisterVariable (&gl_fogdensity);
7504                 Cvar_RegisterVariable (&gl_fogred);
7505                 Cvar_RegisterVariable (&gl_foggreen);
7506                 Cvar_RegisterVariable (&gl_fogblue);
7507                 Cvar_RegisterVariable (&gl_fogstart);
7508                 Cvar_RegisterVariable (&gl_fogend);
7509                 Cvar_RegisterVariable (&gl_skyclip);
7510         }
7511         Cvar_RegisterVariable(&r_motionblur);
7512         Cvar_RegisterVariable(&r_motionblur_maxblur);
7513         Cvar_RegisterVariable(&r_motionblur_bmin);
7514         Cvar_RegisterVariable(&r_motionblur_vmin);
7515         Cvar_RegisterVariable(&r_motionblur_vmax);
7516         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7517         Cvar_RegisterVariable(&r_motionblur_randomize);
7518         Cvar_RegisterVariable(&r_damageblur);
7519         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7520         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7521         Cvar_RegisterVariable(&r_equalize_entities_by);
7522         Cvar_RegisterVariable(&r_equalize_entities_to);
7523         Cvar_RegisterVariable(&r_depthfirst);
7524         Cvar_RegisterVariable(&r_useinfinitefarclip);
7525         Cvar_RegisterVariable(&r_farclip_base);
7526         Cvar_RegisterVariable(&r_farclip_world);
7527         Cvar_RegisterVariable(&r_nearclip);
7528         Cvar_RegisterVariable(&r_showbboxes);
7529         Cvar_RegisterVariable(&r_showsurfaces);
7530         Cvar_RegisterVariable(&r_showtris);
7531         Cvar_RegisterVariable(&r_shownormals);
7532         Cvar_RegisterVariable(&r_showlighting);
7533         Cvar_RegisterVariable(&r_showshadowvolumes);
7534         Cvar_RegisterVariable(&r_showcollisionbrushes);
7535         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7536         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7537         Cvar_RegisterVariable(&r_showdisabledepthtest);
7538         Cvar_RegisterVariable(&r_drawportals);
7539         Cvar_RegisterVariable(&r_drawentities);
7540         Cvar_RegisterVariable(&r_draw2d);
7541         Cvar_RegisterVariable(&r_drawworld);
7542         Cvar_RegisterVariable(&r_cullentities_trace);
7543         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7544         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7545         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7546         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7547         Cvar_RegisterVariable(&r_drawviewmodel);
7548         Cvar_RegisterVariable(&r_drawexteriormodel);
7549         Cvar_RegisterVariable(&r_speeds);
7550         Cvar_RegisterVariable(&r_fullbrights);
7551         Cvar_RegisterVariable(&r_wateralpha);
7552         Cvar_RegisterVariable(&r_dynamic);
7553         Cvar_RegisterVariable(&r_fakelight);
7554         Cvar_RegisterVariable(&r_fakelight_intensity);
7555         Cvar_RegisterVariable(&r_fullbright);
7556         Cvar_RegisterVariable(&r_shadows);
7557         Cvar_RegisterVariable(&r_shadows_darken);
7558         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7559         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7560         Cvar_RegisterVariable(&r_shadows_throwdistance);
7561         Cvar_RegisterVariable(&r_shadows_throwdirection);
7562         Cvar_RegisterVariable(&r_shadows_focus);
7563         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7564         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7565         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7566         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7567         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7568         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7569         Cvar_RegisterVariable(&r_fog_exp2);
7570         Cvar_RegisterVariable(&r_drawfog);
7571         Cvar_RegisterVariable(&r_transparentdepthmasking);
7572         Cvar_RegisterVariable(&r_texture_dds_load);
7573         Cvar_RegisterVariable(&r_texture_dds_save);
7574         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7575         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7576         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7577         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7578         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7579         Cvar_RegisterVariable(&r_textureunits);
7580         Cvar_RegisterVariable(&gl_combine);
7581         Cvar_RegisterVariable(&r_glsl);
7582         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7583         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7584         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7585         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7586         Cvar_RegisterVariable(&r_glsl_postprocess);
7587         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7588         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7589         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7590         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7591         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
7592         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
7593         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
7594         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
7595
7596         Cvar_RegisterVariable(&r_water);
7597         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7598         Cvar_RegisterVariable(&r_water_clippingplanebias);
7599         Cvar_RegisterVariable(&r_water_refractdistort);
7600         Cvar_RegisterVariable(&r_water_reflectdistort);
7601         Cvar_RegisterVariable(&r_water_scissormode);
7602         Cvar_RegisterVariable(&r_lerpsprites);
7603         Cvar_RegisterVariable(&r_lerpmodels);
7604         Cvar_RegisterVariable(&r_lerplightstyles);
7605         Cvar_RegisterVariable(&r_waterscroll);
7606         Cvar_RegisterVariable(&r_bloom);
7607         Cvar_RegisterVariable(&r_bloom_colorscale);
7608         Cvar_RegisterVariable(&r_bloom_brighten);
7609         Cvar_RegisterVariable(&r_bloom_blur);
7610         Cvar_RegisterVariable(&r_bloom_resolution);
7611         Cvar_RegisterVariable(&r_bloom_colorexponent);
7612         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7613         Cvar_RegisterVariable(&r_hdr);
7614         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7615         Cvar_RegisterVariable(&r_hdr_glowintensity);
7616         Cvar_RegisterVariable(&r_hdr_range);
7617         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7618         Cvar_RegisterVariable(&developer_texturelogging);
7619         Cvar_RegisterVariable(&gl_lightmaps);
7620         Cvar_RegisterVariable(&r_test);
7621         Cvar_RegisterVariable(&r_glsl_saturation);
7622         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7623         Cvar_RegisterVariable(&r_framedatasize);
7624         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7625                 Cvar_SetValue("r_fullbrights", 0);
7626         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7627
7628         Cvar_RegisterVariable(&r_track_sprites);
7629         Cvar_RegisterVariable(&r_track_sprites_flags);
7630         Cvar_RegisterVariable(&r_track_sprites_scalew);
7631         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7632         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7633         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7634         Cvar_RegisterVariable(&r_overheadsprites_scalex);
7635         Cvar_RegisterVariable(&r_overheadsprites_scaley);
7636 }
7637
7638 extern void R_Textures_Init(void);
7639 extern void GL_Draw_Init(void);
7640 extern void GL_Main_Init(void);
7641 extern void R_Shadow_Init(void);
7642 extern void R_Sky_Init(void);
7643 extern void GL_Surf_Init(void);
7644 extern void R_Particles_Init(void);
7645 extern void R_Explosion_Init(void);
7646 extern void gl_backend_init(void);
7647 extern void Sbar_Init(void);
7648 extern void R_LightningBeams_Init(void);
7649 extern void Mod_RenderInit(void);
7650 extern void Font_Init(void);
7651
7652 void Render_Init(void)
7653 {
7654         gl_backend_init();
7655         R_Textures_Init();
7656         GL_Main_Init();
7657         Font_Init();
7658         GL_Draw_Init();
7659         R_Shadow_Init();
7660         R_Sky_Init();
7661         GL_Surf_Init();
7662         Sbar_Init();
7663         R_Particles_Init();
7664         R_Explosion_Init();
7665         R_LightningBeams_Init();
7666         Mod_RenderInit();
7667 }
7668
7669 /*
7670 ===============
7671 GL_Init
7672 ===============
7673 */
7674 extern char *ENGINE_EXTENSIONS;
7675 void GL_Init (void)
7676 {
7677         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7678         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7679         gl_version = (const char *)qglGetString(GL_VERSION);
7680         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7681
7682         if (!gl_extensions)
7683                 gl_extensions = "";
7684         if (!gl_platformextensions)
7685                 gl_platformextensions = "";
7686
7687         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7688         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7689         Con_Printf("GL_VERSION: %s\n", gl_version);
7690         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7691         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7692
7693         VID_CheckExtensions();
7694
7695         // LordHavoc: report supported extensions
7696         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7697
7698         // clear to black (loading plaque will be seen over this)
7699         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7700 }
7701
7702 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7703 {
7704         int i;
7705         mplane_t *p;
7706         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7707         {
7708                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7709                 if (i == 4)
7710                         continue;
7711                 p = r_refdef.view.frustum + i;
7712                 switch(p->signbits)
7713                 {
7714                 default:
7715                 case 0:
7716                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7717                                 return true;
7718                         break;
7719                 case 1:
7720                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7721                                 return true;
7722                         break;
7723                 case 2:
7724                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7725                                 return true;
7726                         break;
7727                 case 3:
7728                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7729                                 return true;
7730                         break;
7731                 case 4:
7732                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7733                                 return true;
7734                         break;
7735                 case 5:
7736                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7737                                 return true;
7738                         break;
7739                 case 6:
7740                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7741                                 return true;
7742                         break;
7743                 case 7:
7744                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7745                                 return true;
7746                         break;
7747                 }
7748         }
7749         return false;
7750 }
7751
7752 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7753 {
7754         int i;
7755         const mplane_t *p;
7756         for (i = 0;i < numplanes;i++)
7757         {
7758                 p = planes + i;
7759                 switch(p->signbits)
7760                 {
7761                 default:
7762                 case 0:
7763                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7764                                 return true;
7765                         break;
7766                 case 1:
7767                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7768                                 return true;
7769                         break;
7770                 case 2:
7771                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7772                                 return true;
7773                         break;
7774                 case 3:
7775                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7776                                 return true;
7777                         break;
7778                 case 4:
7779                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7780                                 return true;
7781                         break;
7782                 case 5:
7783                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7784                                 return true;
7785                         break;
7786                 case 6:
7787                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7788                                 return true;
7789                         break;
7790                 case 7:
7791                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7792                                 return true;
7793                         break;
7794                 }
7795         }
7796         return false;
7797 }
7798
7799 //==================================================================================
7800
7801 // LordHavoc: this stores temporary data used within the same frame
7802
7803 typedef struct r_framedata_mem_s
7804 {
7805         struct r_framedata_mem_s *purge; // older mem block to free on next frame
7806         size_t size; // how much usable space
7807         size_t current; // how much space in use
7808         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7809         size_t wantedsize; // how much space was allocated
7810         unsigned char *data; // start of real data (16byte aligned)
7811 }
7812 r_framedata_mem_t;
7813
7814 static r_framedata_mem_t *r_framedata_mem;
7815
7816 void R_FrameData_Reset(void)
7817 {
7818         while (r_framedata_mem)
7819         {
7820                 r_framedata_mem_t *next = r_framedata_mem->purge;
7821                 Mem_Free(r_framedata_mem);
7822                 r_framedata_mem = next;
7823         }
7824 }
7825
7826 void R_FrameData_Resize(void)
7827 {
7828         size_t wantedsize;
7829         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7830         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7831         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7832         {
7833                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
7834                 newmem->wantedsize = wantedsize;
7835                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7836                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7837                 newmem->current = 0;
7838                 newmem->mark = 0;
7839                 newmem->purge = r_framedata_mem;
7840                 r_framedata_mem = newmem;
7841         }
7842 }
7843
7844 void R_FrameData_NewFrame(void)
7845 {
7846         R_FrameData_Resize();
7847         if (!r_framedata_mem)
7848                 return;
7849         // if we ran out of space on the last frame, free the old memory now
7850         while (r_framedata_mem->purge)
7851         {
7852                 // repeatedly remove the second item in the list, leaving only head
7853                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7854                 Mem_Free(r_framedata_mem->purge);
7855                 r_framedata_mem->purge = next;
7856         }
7857         // reset the current mem pointer
7858         r_framedata_mem->current = 0;
7859         r_framedata_mem->mark = 0;
7860 }
7861
7862 void *R_FrameData_Alloc(size_t size)
7863 {
7864         void *data;
7865
7866         // align to 16 byte boundary - the data pointer is already aligned, so we
7867         // only need to ensure the size of every allocation is also aligned
7868         size = (size + 15) & ~15;
7869
7870         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
7871         {
7872                 // emergency - we ran out of space, allocate more memory
7873                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
7874                 R_FrameData_Resize();
7875         }
7876
7877         data = r_framedata_mem->data + r_framedata_mem->current;
7878         r_framedata_mem->current += size;
7879
7880         // count the usage for stats
7881         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
7882         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
7883
7884         return (void *)data;
7885 }
7886
7887 void *R_FrameData_Store(size_t size, void *data)
7888 {
7889         void *d = R_FrameData_Alloc(size);
7890         if (d && data)
7891                 memcpy(d, data, size);
7892         return d;
7893 }
7894
7895 void R_FrameData_SetMark(void)
7896 {
7897         if (!r_framedata_mem)
7898                 return;
7899         r_framedata_mem->mark = r_framedata_mem->current;
7900 }
7901
7902 void R_FrameData_ReturnToMark(void)
7903 {
7904         if (!r_framedata_mem)
7905                 return;
7906         r_framedata_mem->current = r_framedata_mem->mark;
7907 }
7908
7909 //==================================================================================
7910
7911 // LordHavoc: animcache originally written by Echon, rewritten since then
7912
7913 /**
7914  * Animation cache prevents re-generating mesh data for an animated model
7915  * multiple times in one frame for lighting, shadowing, reflections, etc.
7916  */
7917
7918 void R_AnimCache_Free(void)
7919 {
7920 }
7921
7922 void R_AnimCache_ClearCache(void)
7923 {
7924         int i;
7925         entity_render_t *ent;
7926
7927         for (i = 0;i < r_refdef.scene.numentities;i++)
7928         {
7929                 ent = r_refdef.scene.entities[i];
7930                 ent->animcache_vertex3f = NULL;
7931                 ent->animcache_normal3f = NULL;
7932                 ent->animcache_svector3f = NULL;
7933                 ent->animcache_tvector3f = NULL;
7934                 ent->animcache_vertexmesh = NULL;
7935                 ent->animcache_vertex3fbuffer = NULL;
7936                 ent->animcache_vertexmeshbuffer = NULL;
7937         }
7938 }
7939
7940 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7941 {
7942         int i;
7943
7944         // check if we need the meshbuffers
7945         if (!vid.useinterleavedarrays)
7946                 return;
7947
7948         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7949                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7950         // TODO: upload vertex3f buffer?
7951         if (ent->animcache_vertexmesh)
7952         {
7953                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7954                 for (i = 0;i < numvertices;i++)
7955                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7956                 if (ent->animcache_svector3f)
7957                         for (i = 0;i < numvertices;i++)
7958                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7959                 if (ent->animcache_tvector3f)
7960                         for (i = 0;i < numvertices;i++)
7961                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7962                 if (ent->animcache_normal3f)
7963                         for (i = 0;i < numvertices;i++)
7964                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7965                 // TODO: upload vertexmeshbuffer?
7966         }
7967 }
7968
7969 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7970 {
7971         dp_model_t *model = ent->model;
7972         int numvertices;
7973         // see if it's already cached this frame
7974         if (ent->animcache_vertex3f)
7975         {
7976                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7977                 if (wantnormals || wanttangents)
7978                 {
7979                         if (ent->animcache_normal3f)
7980                                 wantnormals = false;
7981                         if (ent->animcache_svector3f)
7982                                 wanttangents = false;
7983                         if (wantnormals || wanttangents)
7984                         {
7985                                 numvertices = model->surfmesh.num_vertices;
7986                                 if (wantnormals)
7987                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7988                                 if (wanttangents)
7989                                 {
7990                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7991                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7992                                 }
7993                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7994                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7995                         }
7996                 }
7997         }
7998         else
7999         {
8000                 // see if this ent is worth caching
8001                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
8002                         return false;
8003                 // get some memory for this entity and generate mesh data
8004                 numvertices = model->surfmesh.num_vertices;
8005                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
8006                 if (wantnormals)
8007                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
8008                 if (wanttangents)
8009                 {
8010                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
8011                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
8012                 }
8013                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
8014                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
8015         }
8016         return true;
8017 }
8018
8019 void R_AnimCache_CacheVisibleEntities(void)
8020 {
8021         int i;
8022         qboolean wantnormals = true;
8023         qboolean wanttangents = !r_showsurfaces.integer;
8024
8025         switch(vid.renderpath)
8026         {
8027         case RENDERPATH_GL20:
8028         case RENDERPATH_CGGL:
8029         case RENDERPATH_D3D9:
8030         case RENDERPATH_D3D10:
8031         case RENDERPATH_D3D11:
8032         case RENDERPATH_GLES2:
8033                 break;
8034         case RENDERPATH_GL13:
8035         case RENDERPATH_GL11:
8036                 wanttangents = false;
8037                 break;
8038         case RENDERPATH_SOFT:
8039                 break;
8040         }
8041
8042         if (r_shownormals.integer)
8043                 wanttangents = wantnormals = true;
8044
8045         // TODO: thread this
8046         // NOTE: R_PrepareRTLights() also caches entities
8047
8048         for (i = 0;i < r_refdef.scene.numentities;i++)
8049                 if (r_refdef.viewcache.entityvisible[i])
8050                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
8051 }
8052
8053 //==================================================================================
8054
8055 static void R_View_UpdateEntityLighting (void)
8056 {
8057         int i;
8058         entity_render_t *ent;
8059         vec3_t tempdiffusenormal, avg;
8060         vec_t f, fa, fd, fdd;
8061         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
8062
8063         for (i = 0;i < r_refdef.scene.numentities;i++)
8064         {
8065                 ent = r_refdef.scene.entities[i];
8066
8067                 // skip unseen models
8068                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
8069                         continue;
8070
8071                 // skip bsp models
8072                 if (ent->model && ent->model->brush.num_leafs)
8073                 {
8074                         // TODO: use modellight for r_ambient settings on world?
8075                         VectorSet(ent->modellight_ambient, 0, 0, 0);
8076                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
8077                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
8078                         continue;
8079                 }
8080
8081                 // fetch the lighting from the worldmodel data
8082                 VectorClear(ent->modellight_ambient);
8083                 VectorClear(ent->modellight_diffuse);
8084                 VectorClear(tempdiffusenormal);
8085                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
8086                 {
8087                         vec3_t org;
8088                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8089
8090                         // complete lightning for lit sprites
8091                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
8092                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
8093                         {
8094                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
8095                                         org[2] = org[2] + r_overheadsprites_pushback.value;
8096                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
8097                         }
8098                         else
8099                                 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
8100
8101                         if(ent->flags & RENDER_EQUALIZE)
8102                         {
8103                                 // first fix up ambient lighting...
8104                                 if(r_equalize_entities_minambient.value > 0)
8105                                 {
8106                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
8107                                         if(fd > 0)
8108                                         {
8109                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
8110                                                 if(fa < r_equalize_entities_minambient.value * fd)
8111                                                 {
8112                                                         // solve:
8113                                                         //   fa'/fd' = minambient
8114                                                         //   fa'+0.25*fd' = fa+0.25*fd
8115                                                         //   ...
8116                                                         //   fa' = fd' * minambient
8117                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
8118                                                         //   ...
8119                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
8120                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
8121                                                         //   ...
8122                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
8123                                                         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
8124                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
8125                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
8126                                                 }
8127                                         }
8128                                 }
8129
8130                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
8131                                 {
8132                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
8133                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
8134                                         f = fa + 0.25 * fd;
8135                                         if(f > 0)
8136                                         {
8137                                                 // adjust brightness and saturation to target
8138                                                 avg[0] = avg[1] = avg[2] = fa / f;
8139                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
8140                                                 avg[0] = avg[1] = avg[2] = fd / f;
8141                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
8142                                         }
8143                                 }
8144                         }
8145                 }
8146                 else // highly rare
8147                         VectorSet(ent->modellight_ambient, 1, 1, 1);
8148
8149                 // move the light direction into modelspace coordinates for lighting code
8150                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
8151                 if(VectorLength2(ent->modellight_lightdir) == 0)
8152                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
8153                 VectorNormalize(ent->modellight_lightdir);
8154         }
8155 }
8156
8157 #define MAX_LINEOFSIGHTTRACES 64
8158
8159 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
8160 {
8161         int i;
8162         vec3_t boxmins, boxmaxs;
8163         vec3_t start;
8164         vec3_t end;
8165         dp_model_t *model = r_refdef.scene.worldmodel;
8166
8167         if (!model || !model->brush.TraceLineOfSight)
8168                 return true;
8169
8170         // expand the box a little
8171         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
8172         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
8173         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
8174         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
8175         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
8176         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
8177
8178         // return true if eye is inside enlarged box
8179         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
8180                 return true;
8181
8182         // try center
8183         VectorCopy(eye, start);
8184         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
8185         if (model->brush.TraceLineOfSight(model, start, end))
8186                 return true;
8187
8188         // try various random positions
8189         for (i = 0;i < numsamples;i++)
8190         {
8191                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
8192                 if (model->brush.TraceLineOfSight(model, start, end))
8193                         return true;
8194         }
8195
8196         return false;
8197 }
8198
8199
8200 static void R_View_UpdateEntityVisible (void)
8201 {
8202         int i;
8203         int renderimask;
8204         int samples;
8205         entity_render_t *ent;
8206
8207         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8208                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8209                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
8210                 :                                                          RENDER_EXTERIORMODEL;
8211         if (!r_drawviewmodel.integer)
8212                 renderimask |= RENDER_VIEWMODEL;
8213         if (!r_drawexteriormodel.integer)
8214                 renderimask |= RENDER_EXTERIORMODEL;
8215         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8216         {
8217                 // worldmodel can check visibility
8218                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8219                 for (i = 0;i < r_refdef.scene.numentities;i++)
8220                 {
8221                         ent = r_refdef.scene.entities[i];
8222                         if (!(ent->flags & renderimask))
8223                         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)))
8224                         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))
8225                                 r_refdef.viewcache.entityvisible[i] = true;
8226                 }
8227                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8228                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8229                 {
8230                         for (i = 0;i < r_refdef.scene.numentities;i++)
8231                         {
8232                                 ent = r_refdef.scene.entities[i];
8233                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8234                                 {
8235                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8236                                         if (samples < 0)
8237                                                 continue; // temp entities do pvs only
8238                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8239                                                 ent->last_trace_visibility = realtime;
8240                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8241                                                 r_refdef.viewcache.entityvisible[i] = 0;
8242                                 }
8243                         }
8244                 }
8245         }
8246         else
8247         {
8248                 // no worldmodel or it can't check visibility
8249                 for (i = 0;i < r_refdef.scene.numentities;i++)
8250                 {
8251                         ent = r_refdef.scene.entities[i];
8252                         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));
8253                 }
8254         }
8255 }
8256
8257 /// only used if skyrendermasked, and normally returns false
8258 int R_DrawBrushModelsSky (void)
8259 {
8260         int i, sky;
8261         entity_render_t *ent;
8262
8263         sky = false;
8264         for (i = 0;i < r_refdef.scene.numentities;i++)
8265         {
8266                 if (!r_refdef.viewcache.entityvisible[i])
8267                         continue;
8268                 ent = r_refdef.scene.entities[i];
8269                 if (!ent->model || !ent->model->DrawSky)
8270                         continue;
8271                 ent->model->DrawSky(ent);
8272                 sky = true;
8273         }
8274         return sky;
8275 }
8276
8277 static void R_DrawNoModel(entity_render_t *ent);
8278 static void R_DrawModels(void)
8279 {
8280         int i;
8281         entity_render_t *ent;
8282
8283         for (i = 0;i < r_refdef.scene.numentities;i++)
8284         {
8285                 if (!r_refdef.viewcache.entityvisible[i])
8286                         continue;
8287                 ent = r_refdef.scene.entities[i];
8288                 r_refdef.stats.entities++;
8289                 if (ent->model && ent->model->Draw != NULL)
8290                         ent->model->Draw(ent);
8291                 else
8292                         R_DrawNoModel(ent);
8293         }
8294 }
8295
8296 static void R_DrawModelsDepth(void)
8297 {
8298         int i;
8299         entity_render_t *ent;
8300
8301         for (i = 0;i < r_refdef.scene.numentities;i++)
8302         {
8303                 if (!r_refdef.viewcache.entityvisible[i])
8304                         continue;
8305                 ent = r_refdef.scene.entities[i];
8306                 if (ent->model && ent->model->DrawDepth != NULL)
8307                         ent->model->DrawDepth(ent);
8308         }
8309 }
8310
8311 static void R_DrawModelsDebug(void)
8312 {
8313         int i;
8314         entity_render_t *ent;
8315
8316         for (i = 0;i < r_refdef.scene.numentities;i++)
8317         {
8318                 if (!r_refdef.viewcache.entityvisible[i])
8319                         continue;
8320                 ent = r_refdef.scene.entities[i];
8321                 if (ent->model && ent->model->DrawDebug != NULL)
8322                         ent->model->DrawDebug(ent);
8323         }
8324 }
8325
8326 static void R_DrawModelsAddWaterPlanes(void)
8327 {
8328         int i;
8329         entity_render_t *ent;
8330
8331         for (i = 0;i < r_refdef.scene.numentities;i++)
8332         {
8333                 if (!r_refdef.viewcache.entityvisible[i])
8334                         continue;
8335                 ent = r_refdef.scene.entities[i];
8336                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8337                         ent->model->DrawAddWaterPlanes(ent);
8338         }
8339 }
8340
8341 static void R_View_SetFrustum(const int *scissor)
8342 {
8343         int i;
8344         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8345         vec3_t forward, left, up, origin, v;
8346
8347         if(scissor)
8348         {
8349                 // flipped x coordinates (because x points left here)
8350                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8351                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8352
8353                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8354                 switch(vid.renderpath)
8355                 {
8356                         case RENDERPATH_D3D9:
8357                         case RENDERPATH_D3D10:
8358                         case RENDERPATH_D3D11:
8359                         case RENDERPATH_SOFT:
8360                                 // non-flipped y coordinates
8361                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8362                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8363                                 break;
8364                         case RENDERPATH_GL11:
8365                         case RENDERPATH_GL13:
8366                         case RENDERPATH_GL20:
8367                         case RENDERPATH_CGGL:
8368                         case RENDERPATH_GLES2:
8369                                 // non-flipped y coordinates
8370                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8371                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8372                                 break;
8373                 }
8374         }
8375
8376         // we can't trust r_refdef.view.forward and friends in reflected scenes
8377         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8378
8379 #if 0
8380         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8381         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8382         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8383         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8384         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8385         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8386         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8387         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8388         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8389         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8390         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8391         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8392 #endif
8393
8394 #if 0
8395         zNear = r_refdef.nearclip;
8396         nudge = 1.0 - 1.0 / (1<<23);
8397         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8398         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8399         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8400         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8401         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8402         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8403         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8404         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8405 #endif
8406
8407
8408
8409 #if 0
8410         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8411         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8412         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8413         r_refdef.view.frustum[0].dist = m[15] - m[12];
8414
8415         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8416         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8417         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8418         r_refdef.view.frustum[1].dist = m[15] + m[12];
8419
8420         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8421         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8422         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8423         r_refdef.view.frustum[2].dist = m[15] - m[13];
8424
8425         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8426         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8427         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8428         r_refdef.view.frustum[3].dist = m[15] + m[13];
8429
8430         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8431         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8432         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8433         r_refdef.view.frustum[4].dist = m[15] - m[14];
8434
8435         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8436         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8437         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8438         r_refdef.view.frustum[5].dist = m[15] + m[14];
8439 #endif
8440
8441         if (r_refdef.view.useperspective)
8442         {
8443                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8444                 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]);
8445                 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]);
8446                 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]);
8447                 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]);
8448
8449                 // then the normals from the corners relative to origin
8450                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8451                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8452                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8453                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8454
8455                 // in a NORMAL view, forward cross left == up
8456                 // in a REFLECTED view, forward cross left == down
8457                 // so our cross products above need to be adjusted for a left handed coordinate system
8458                 CrossProduct(forward, left, v);
8459                 if(DotProduct(v, up) < 0)
8460                 {
8461                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8462                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8463                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8464                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8465                 }
8466
8467                 // Leaving those out was a mistake, those were in the old code, and they
8468                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8469                 // I couldn't reproduce it after adding those normalizations. --blub
8470                 VectorNormalize(r_refdef.view.frustum[0].normal);
8471                 VectorNormalize(r_refdef.view.frustum[1].normal);
8472                 VectorNormalize(r_refdef.view.frustum[2].normal);
8473                 VectorNormalize(r_refdef.view.frustum[3].normal);
8474
8475                 // make the corners absolute
8476                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8477                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8478                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8479                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8480
8481                 // one more normal
8482                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8483
8484                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8485                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8486                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8487                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8488                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8489         }
8490         else
8491         {
8492                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8493                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8494                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8495                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8496                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8497                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8498                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8499                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8500                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8501                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8502         }
8503         r_refdef.view.numfrustumplanes = 5;
8504
8505         if (r_refdef.view.useclipplane)
8506         {
8507                 r_refdef.view.numfrustumplanes = 6;
8508                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8509         }
8510
8511         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8512                 PlaneClassify(r_refdef.view.frustum + i);
8513
8514         // LordHavoc: note to all quake engine coders, Quake had a special case
8515         // for 90 degrees which assumed a square view (wrong), so I removed it,
8516         // Quake2 has it disabled as well.
8517
8518         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8519         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8520         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8521         //PlaneClassify(&frustum[0]);
8522
8523         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8524         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8525         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8526         //PlaneClassify(&frustum[1]);
8527
8528         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8529         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8530         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8531         //PlaneClassify(&frustum[2]);
8532
8533         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8534         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8535         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8536         //PlaneClassify(&frustum[3]);
8537
8538         // nearclip plane
8539         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8540         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8541         //PlaneClassify(&frustum[4]);
8542 }
8543
8544 void R_View_UpdateWithScissor(const int *myscissor)
8545 {
8546         R_Main_ResizeViewCache();
8547         R_View_SetFrustum(myscissor);
8548         R_View_WorldVisibility(r_refdef.view.useclipplane);
8549         R_View_UpdateEntityVisible();
8550         R_View_UpdateEntityLighting();
8551 }
8552
8553 void R_View_Update(void)
8554 {
8555         R_Main_ResizeViewCache();
8556         R_View_SetFrustum(NULL);
8557         R_View_WorldVisibility(r_refdef.view.useclipplane);
8558         R_View_UpdateEntityVisible();
8559         R_View_UpdateEntityLighting();
8560 }
8561
8562 void R_SetupView(qboolean allowwaterclippingplane)
8563 {
8564         const float *customclipplane = NULL;
8565         float plane[4];
8566         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8567         {
8568                 // LordHavoc: couldn't figure out how to make this approach the
8569                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8570                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8571                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8572                         dist = r_refdef.view.clipplane.dist;
8573                 plane[0] = r_refdef.view.clipplane.normal[0];
8574                 plane[1] = r_refdef.view.clipplane.normal[1];
8575                 plane[2] = r_refdef.view.clipplane.normal[2];
8576                 plane[3] = dist;
8577                 customclipplane = plane;
8578         }
8579
8580         if (!r_refdef.view.useperspective)
8581                 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);
8582         else if (vid.stencil && r_useinfinitefarclip.integer)
8583                 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);
8584         else
8585                 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);
8586         R_SetViewport(&r_refdef.view.viewport);
8587 }
8588
8589 void R_EntityMatrix(const matrix4x4_t *matrix)
8590 {
8591         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8592         {
8593                 gl_modelmatrixchanged = false;
8594                 gl_modelmatrix = *matrix;
8595                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8596                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8597                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8598                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8599                 CHECKGLERROR
8600                 switch(vid.renderpath)
8601                 {
8602                 case RENDERPATH_D3D9:
8603 #ifdef SUPPORTD3D
8604                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8605                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8606 #endif
8607                         break;
8608                 case RENDERPATH_D3D10:
8609                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8610                         break;
8611                 case RENDERPATH_D3D11:
8612                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8613                         break;
8614                 case RENDERPATH_CGGL:
8615 #ifdef SUPPORTCG
8616                         CHECKCGERROR
8617                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8618                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8619 #endif
8620                         break;
8621                 case RENDERPATH_GL13:
8622                 case RENDERPATH_GL11:
8623                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8624                         break;
8625                 case RENDERPATH_SOFT:
8626                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
8627                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
8628                         break;
8629                 case RENDERPATH_GL20:
8630                 case RENDERPATH_GLES2:
8631                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8632                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8633                         break;
8634                 }
8635         }
8636 }
8637
8638 void R_ResetViewRendering2D(void)
8639 {
8640         r_viewport_t viewport;
8641         DrawQ_Finish();
8642
8643         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8644         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);
8645         R_SetViewport(&viewport);
8646         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8647         GL_Color(1, 1, 1, 1);
8648         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8649         GL_BlendFunc(GL_ONE, GL_ZERO);
8650         GL_ScissorTest(false);
8651         GL_DepthMask(false);
8652         GL_DepthRange(0, 1);
8653         GL_DepthTest(false);
8654         GL_DepthFunc(GL_LEQUAL);
8655         R_EntityMatrix(&identitymatrix);
8656         R_Mesh_ResetTextureState();
8657         GL_PolygonOffset(0, 0);
8658         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8659         switch(vid.renderpath)
8660         {
8661         case RENDERPATH_GL11:
8662         case RENDERPATH_GL13:
8663         case RENDERPATH_GL20:
8664         case RENDERPATH_CGGL:
8665         case RENDERPATH_GLES2:
8666                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8667                 break;
8668         case RENDERPATH_D3D9:
8669         case RENDERPATH_D3D10:
8670         case RENDERPATH_D3D11:
8671         case RENDERPATH_SOFT:
8672                 break;
8673         }
8674         GL_CullFace(GL_NONE);
8675 }
8676
8677 void R_ResetViewRendering3D(void)
8678 {
8679         DrawQ_Finish();
8680
8681         R_SetupView(true);
8682         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8683         GL_Color(1, 1, 1, 1);
8684         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8685         GL_BlendFunc(GL_ONE, GL_ZERO);
8686         GL_ScissorTest(true);
8687         GL_DepthMask(true);
8688         GL_DepthRange(0, 1);
8689         GL_DepthTest(true);
8690         GL_DepthFunc(GL_LEQUAL);
8691         R_EntityMatrix(&identitymatrix);
8692         R_Mesh_ResetTextureState();
8693         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8694         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8695         switch(vid.renderpath)
8696         {
8697         case RENDERPATH_GL11:
8698         case RENDERPATH_GL13:
8699         case RENDERPATH_GL20:
8700         case RENDERPATH_CGGL:
8701         case RENDERPATH_GLES2:
8702                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8703                 break;
8704         case RENDERPATH_D3D9:
8705         case RENDERPATH_D3D10:
8706         case RENDERPATH_D3D11:
8707         case RENDERPATH_SOFT:
8708                 break;
8709         }
8710         GL_CullFace(r_refdef.view.cullface_back);
8711 }
8712
8713 /*
8714 ================
8715 R_RenderView_UpdateViewVectors
8716 ================
8717 */
8718 static void R_RenderView_UpdateViewVectors(void)
8719 {
8720         // break apart the view matrix into vectors for various purposes
8721         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8722         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8723         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8724         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8725         // make an inverted copy of the view matrix for tracking sprites
8726         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8727 }
8728
8729 void R_RenderScene(void);
8730 void R_RenderWaterPlanes(void);
8731
8732 static void R_Water_StartFrame(void)
8733 {
8734         int i;
8735         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8736         r_waterstate_waterplane_t *p;
8737
8738         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8739                 return;
8740
8741         switch(vid.renderpath)
8742         {
8743         case RENDERPATH_GL20:
8744         case RENDERPATH_CGGL:
8745         case RENDERPATH_D3D9:
8746         case RENDERPATH_D3D10:
8747         case RENDERPATH_D3D11:
8748         case RENDERPATH_SOFT:
8749         case RENDERPATH_GLES2:
8750                 break;
8751         case RENDERPATH_GL13:
8752         case RENDERPATH_GL11:
8753                 return;
8754         }
8755
8756         // set waterwidth and waterheight to the water resolution that will be
8757         // used (often less than the screen resolution for faster rendering)
8758         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8759         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8760
8761         // calculate desired texture sizes
8762         // can't use water if the card does not support the texture size
8763         if (!r_water.integer || r_showsurfaces.integer)
8764                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8765         else if (vid.support.arb_texture_non_power_of_two)
8766         {
8767                 texturewidth = waterwidth;
8768                 textureheight = waterheight;
8769                 camerawidth = waterwidth;
8770                 cameraheight = waterheight;
8771         }
8772         else
8773         {
8774                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8775                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8776                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8777                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8778         }
8779
8780         // allocate textures as needed
8781         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8782         {
8783                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8784                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8785                 {
8786                         if (p->texture_refraction)
8787                                 R_FreeTexture(p->texture_refraction);
8788                         p->texture_refraction = NULL;
8789                         if (p->texture_reflection)
8790                                 R_FreeTexture(p->texture_reflection);
8791                         p->texture_reflection = NULL;
8792                         if (p->texture_camera)
8793                                 R_FreeTexture(p->texture_camera);
8794                         p->texture_camera = NULL;
8795                 }
8796                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8797                 r_waterstate.texturewidth = texturewidth;
8798                 r_waterstate.textureheight = textureheight;
8799                 r_waterstate.camerawidth = camerawidth;
8800                 r_waterstate.cameraheight = cameraheight;
8801         }
8802
8803         if (r_waterstate.texturewidth)
8804         {
8805                 r_waterstate.enabled = true;
8806
8807                 // when doing a reduced render (HDR) we want to use a smaller area
8808                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8809                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8810
8811                 // set up variables that will be used in shader setup
8812                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8813                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8814                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8815                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8816         }
8817
8818         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8819         r_waterstate.numwaterplanes = 0;
8820 }
8821
8822 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8823 {
8824         int triangleindex, planeindex;
8825         const int *e;
8826         vec3_t vert[3];
8827         vec3_t normal;
8828         vec3_t center;
8829         mplane_t plane;
8830         r_waterstate_waterplane_t *p;
8831         texture_t *t = R_GetCurrentTexture(surface->texture);
8832
8833         // just use the first triangle with a valid normal for any decisions
8834         VectorClear(normal);
8835         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8836         {
8837                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8838                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8839                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8840                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8841                 if (VectorLength2(normal) >= 0.001)
8842                         break;
8843         }
8844
8845         VectorCopy(normal, plane.normal);
8846         VectorNormalize(plane.normal);
8847         plane.dist = DotProduct(vert[0], plane.normal);
8848         PlaneClassify(&plane);
8849         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8850         {
8851                 // skip backfaces (except if nocullface is set)
8852                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8853                         return;
8854                 VectorNegate(plane.normal, plane.normal);
8855                 plane.dist *= -1;
8856                 PlaneClassify(&plane);
8857         }
8858
8859
8860         // find a matching plane if there is one
8861         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8862                 if(p->camera_entity == t->camera_entity)
8863                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8864                                 break;
8865         if (planeindex >= r_waterstate.maxwaterplanes)
8866                 return; // nothing we can do, out of planes
8867
8868         // if this triangle does not fit any known plane rendered this frame, add one
8869         if (planeindex >= r_waterstate.numwaterplanes)
8870         {
8871                 // store the new plane
8872                 r_waterstate.numwaterplanes++;
8873                 p->plane = plane;
8874                 // clear materialflags and pvs
8875                 p->materialflags = 0;
8876                 p->pvsvalid = false;
8877                 p->camera_entity = t->camera_entity;
8878                 VectorCopy(surface->mins, p->mins);
8879                 VectorCopy(surface->maxs, p->maxs);
8880         }
8881         else
8882         {
8883                 // merge mins/maxs
8884                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8885                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8886                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8887                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8888                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8889                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8890         }
8891         // merge this surface's materialflags into the waterplane
8892         p->materialflags |= t->currentmaterialflags;
8893         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8894         {
8895                 // merge this surface's PVS into the waterplane
8896                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8897                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8898                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8899                 {
8900                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8901                         p->pvsvalid = true;
8902                 }
8903         }
8904 }
8905
8906 static void R_Water_ProcessPlanes(void)
8907 {
8908         int myscissor[4];
8909         r_refdef_view_t originalview;
8910         r_refdef_view_t myview;
8911         int planeindex;
8912         r_waterstate_waterplane_t *p;
8913         vec3_t visorigin;
8914
8915         originalview = r_refdef.view;
8916
8917         // make sure enough textures are allocated
8918         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8919         {
8920                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8921                 {
8922                         if (!p->texture_refraction)
8923                                 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);
8924                         if (!p->texture_refraction)
8925                                 goto error;
8926                 }
8927                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8928                 {
8929                         if (!p->texture_camera)
8930                                 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);
8931                         if (!p->texture_camera)
8932                                 goto error;
8933                 }
8934
8935                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8936                 {
8937                         if (!p->texture_reflection)
8938                                 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);
8939                         if (!p->texture_reflection)
8940                                 goto error;
8941                 }
8942         }
8943
8944         // render views
8945         r_refdef.view = originalview;
8946         r_refdef.view.showdebug = false;
8947         r_refdef.view.width = r_waterstate.waterwidth;
8948         r_refdef.view.height = r_waterstate.waterheight;
8949         r_refdef.view.useclipplane = true;
8950         myview = r_refdef.view;
8951         r_waterstate.renderingscene = true;
8952         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8953         {
8954                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8955                 {
8956                         r_refdef.view = myview;
8957                         if(r_water_scissormode.integer)
8958                         {
8959                                 R_SetupView(true);
8960                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8961                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8962                         }
8963
8964                         // render reflected scene and copy into texture
8965                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8966                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8967                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8968                         r_refdef.view.clipplane = p->plane;
8969
8970                         // reverse the cullface settings for this render
8971                         r_refdef.view.cullface_front = GL_FRONT;
8972                         r_refdef.view.cullface_back = GL_BACK;
8973                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8974                         {
8975                                 r_refdef.view.usecustompvs = true;
8976                                 if (p->pvsvalid)
8977                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8978                                 else
8979                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8980                         }
8981
8982                         R_ResetViewRendering3D();
8983                         R_ClearScreen(r_refdef.fogenabled);
8984                         if(r_water_scissormode.integer & 2)
8985                                 R_View_UpdateWithScissor(myscissor);
8986                         else
8987                                 R_View_Update();
8988                         if(r_water_scissormode.integer & 1)
8989                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8990                         R_RenderScene();
8991
8992                         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);
8993                 }
8994
8995                 // render the normal view scene and copy into texture
8996                 // (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)
8997                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8998                 {
8999                         r_refdef.view = myview;
9000                         if(r_water_scissormode.integer)
9001                         {
9002                                 R_SetupView(true);
9003                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
9004                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
9005                         }
9006
9007                         r_waterstate.renderingrefraction = true;
9008
9009                         r_refdef.view.clipplane = p->plane;
9010                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
9011                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
9012
9013                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
9014                         {
9015                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
9016                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
9017                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
9018                                 R_RenderView_UpdateViewVectors();
9019                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
9020                                 {
9021                                         r_refdef.view.usecustompvs = true;
9022                                         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);
9023                                 }
9024                         }
9025
9026                         PlaneClassify(&r_refdef.view.clipplane);
9027
9028                         R_ResetViewRendering3D();
9029                         R_ClearScreen(r_refdef.fogenabled);
9030                         if(r_water_scissormode.integer & 2)
9031                                 R_View_UpdateWithScissor(myscissor);
9032                         else
9033                                 R_View_Update();
9034                         if(r_water_scissormode.integer & 1)
9035                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
9036                         R_RenderScene();
9037
9038                         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);
9039                         r_waterstate.renderingrefraction = false;
9040                 }
9041                 else if (p->materialflags & MATERIALFLAG_CAMERA)
9042                 {
9043                         r_refdef.view = myview;
9044
9045                         r_refdef.view.clipplane = p->plane;
9046                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
9047                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
9048
9049                         r_refdef.view.width = r_waterstate.camerawidth;
9050                         r_refdef.view.height = r_waterstate.cameraheight;
9051                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
9052                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
9053
9054                         if(p->camera_entity)
9055                         {
9056                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
9057                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
9058                         }
9059
9060                         // note: all of the view is used for displaying... so
9061                         // there is no use in scissoring
9062
9063                         // reverse the cullface settings for this render
9064                         r_refdef.view.cullface_front = GL_FRONT;
9065                         r_refdef.view.cullface_back = GL_BACK;
9066                         // also reverse the view matrix
9067                         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
9068                         R_RenderView_UpdateViewVectors();
9069                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
9070                         {
9071                                 r_refdef.view.usecustompvs = true;
9072                                 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);
9073                         }
9074                         
9075                         // camera needs no clipplane
9076                         r_refdef.view.useclipplane = false;
9077
9078                         PlaneClassify(&r_refdef.view.clipplane);
9079
9080                         R_ResetViewRendering3D();
9081                         R_ClearScreen(r_refdef.fogenabled);
9082                         R_View_Update();
9083                         R_RenderScene();
9084
9085                         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);
9086                         r_waterstate.renderingrefraction = false;
9087                 }
9088
9089         }
9090         r_waterstate.renderingscene = false;
9091         r_refdef.view = originalview;
9092         R_ResetViewRendering3D();
9093         R_ClearScreen(r_refdef.fogenabled);
9094         R_View_Update();
9095         return;
9096 error:
9097         r_refdef.view = originalview;
9098         r_waterstate.renderingscene = false;
9099         Cvar_SetValueQuick(&r_water, 0);
9100         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
9101         return;
9102 }
9103
9104 void R_Bloom_StartFrame(void)
9105 {
9106         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
9107
9108         switch(vid.renderpath)
9109         {
9110         case RENDERPATH_GL20:
9111         case RENDERPATH_CGGL:
9112         case RENDERPATH_D3D9:
9113         case RENDERPATH_D3D10:
9114         case RENDERPATH_D3D11:
9115         case RENDERPATH_SOFT:
9116         case RENDERPATH_GLES2:
9117                 break;
9118         case RENDERPATH_GL13:
9119         case RENDERPATH_GL11:
9120                 return;
9121         }
9122
9123         // set bloomwidth and bloomheight to the bloom resolution that will be
9124         // used (often less than the screen resolution for faster rendering)
9125         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
9126         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
9127         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
9128         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
9129         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
9130
9131         // calculate desired texture sizes
9132         if (vid.support.arb_texture_non_power_of_two)
9133         {
9134                 screentexturewidth = r_refdef.view.width;
9135                 screentextureheight = r_refdef.view.height;
9136                 bloomtexturewidth = r_bloomstate.bloomwidth;
9137                 bloomtextureheight = r_bloomstate.bloomheight;
9138         }
9139         else
9140         {
9141                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
9142                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
9143                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
9144                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
9145         }
9146
9147         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))
9148         {
9149                 Cvar_SetValueQuick(&r_hdr, 0);
9150                 Cvar_SetValueQuick(&r_bloom, 0);
9151                 Cvar_SetValueQuick(&r_motionblur, 0);
9152                 Cvar_SetValueQuick(&r_damageblur, 0);
9153         }
9154
9155         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)))
9156                 screentexturewidth = screentextureheight = 0;
9157         if (!r_hdr.integer && !r_bloom.integer)
9158                 bloomtexturewidth = bloomtextureheight = 0;
9159
9160         // allocate textures as needed
9161         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
9162         {
9163                 if (r_bloomstate.texture_screen)
9164                         R_FreeTexture(r_bloomstate.texture_screen);
9165                 r_bloomstate.texture_screen = NULL;
9166                 r_bloomstate.screentexturewidth = screentexturewidth;
9167                 r_bloomstate.screentextureheight = screentextureheight;
9168                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
9169                         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);
9170         }
9171         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
9172         {
9173                 if (r_bloomstate.texture_bloom)
9174                         R_FreeTexture(r_bloomstate.texture_bloom);
9175                 r_bloomstate.texture_bloom = NULL;
9176                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
9177                 r_bloomstate.bloomtextureheight = bloomtextureheight;
9178                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
9179                         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);
9180         }
9181
9182         // when doing a reduced render (HDR) we want to use a smaller area
9183         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
9184         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
9185         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
9186         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
9187         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
9188
9189         // set up a texcoord array for the full resolution screen image
9190         // (we have to keep this around to copy back during final render)
9191         r_bloomstate.screentexcoord2f[0] = 0;
9192         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
9193         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
9194         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
9195         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
9196         r_bloomstate.screentexcoord2f[5] = 0;
9197         r_bloomstate.screentexcoord2f[6] = 0;
9198         r_bloomstate.screentexcoord2f[7] = 0;
9199
9200         // set up a texcoord array for the reduced resolution bloom image
9201         // (which will be additive blended over the screen image)
9202         r_bloomstate.bloomtexcoord2f[0] = 0;
9203         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9204         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9205         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9206         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9207         r_bloomstate.bloomtexcoord2f[5] = 0;
9208         r_bloomstate.bloomtexcoord2f[6] = 0;
9209         r_bloomstate.bloomtexcoord2f[7] = 0;
9210
9211         switch(vid.renderpath)
9212         {
9213         case RENDERPATH_GL11:
9214         case RENDERPATH_GL13:
9215         case RENDERPATH_GL20:
9216         case RENDERPATH_CGGL:
9217         case RENDERPATH_SOFT:
9218         case RENDERPATH_GLES2:
9219                 break;
9220         case RENDERPATH_D3D9:
9221         case RENDERPATH_D3D10:
9222         case RENDERPATH_D3D11:
9223                 {
9224                         int i;
9225                         for (i = 0;i < 4;i++)
9226                         {
9227                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
9228                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
9229                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
9230                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
9231                         }
9232                 }
9233                 break;
9234         }
9235
9236         if (r_hdr.integer || r_bloom.integer)
9237         {
9238                 r_bloomstate.enabled = true;
9239                 r_bloomstate.hdr = r_hdr.integer != 0;
9240         }
9241
9242         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);
9243 }
9244
9245 void R_Bloom_CopyBloomTexture(float colorscale)
9246 {
9247         r_refdef.stats.bloom++;
9248
9249         // scale down screen texture to the bloom texture size
9250         CHECKGLERROR
9251         R_SetViewport(&r_bloomstate.viewport);
9252         GL_BlendFunc(GL_ONE, GL_ZERO);
9253         GL_Color(colorscale, colorscale, colorscale, 1);
9254         // 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...
9255         switch(vid.renderpath)
9256         {
9257         case RENDERPATH_GL11:
9258         case RENDERPATH_GL13:
9259         case RENDERPATH_GL20:
9260         case RENDERPATH_CGGL:
9261         case RENDERPATH_SOFT:
9262         case RENDERPATH_GLES2:
9263                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9264                 break;
9265         case RENDERPATH_D3D9:
9266         case RENDERPATH_D3D10:
9267         case RENDERPATH_D3D11:
9268                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9269                 break;
9270         }
9271         // TODO: do boxfilter scale-down in shader?
9272         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9273         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9274         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9275
9276         // we now have a bloom image in the framebuffer
9277         // copy it into the bloom image texture for later processing
9278         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);
9279         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9280 }
9281
9282 void R_Bloom_CopyHDRTexture(void)
9283 {
9284         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);
9285         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9286 }
9287
9288 void R_Bloom_MakeTexture(void)
9289 {
9290         int x, range, dir;
9291         float xoffset, yoffset, r, brighten;
9292
9293         r_refdef.stats.bloom++;
9294
9295         R_ResetViewRendering2D();
9296
9297         // we have a bloom image in the framebuffer
9298         CHECKGLERROR
9299         R_SetViewport(&r_bloomstate.viewport);
9300
9301         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9302         {
9303                 x *= 2;
9304                 r = bound(0, r_bloom_colorexponent.value / x, 1);
9305                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9306                 GL_Color(r,r,r,1);
9307                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9308                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9309                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9310                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9311
9312                 // copy the vertically blurred bloom view to a texture
9313                 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);
9314                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9315         }
9316
9317         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9318         brighten = r_bloom_brighten.value;
9319         if (r_hdr.integer)
9320                 brighten *= r_hdr_range.value;
9321         brighten = sqrt(brighten);
9322         if(range >= 1)
9323                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9324         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9325
9326         for (dir = 0;dir < 2;dir++)
9327         {
9328                 // blend on at multiple vertical offsets to achieve a vertical blur
9329                 // TODO: do offset blends using GLSL
9330                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9331                 GL_BlendFunc(GL_ONE, GL_ZERO);
9332                 for (x = -range;x <= range;x++)
9333                 {
9334                         if (!dir){xoffset = 0;yoffset = x;}
9335                         else {xoffset = x;yoffset = 0;}
9336                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9337                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9338                         // compute a texcoord array with the specified x and y offset
9339                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9340                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9341                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9342                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9343                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9344                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9345                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9346                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9347                         // this r value looks like a 'dot' particle, fading sharply to
9348                         // black at the edges
9349                         // (probably not realistic but looks good enough)
9350                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9351                         //r = brighten/(range*2+1);
9352                         r = brighten / (range * 2 + 1);
9353                         if(range >= 1)
9354                                 r *= (1 - x*x/(float)(range*range));
9355                         GL_Color(r, r, r, 1);
9356                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9357                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9358                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9359                         GL_BlendFunc(GL_ONE, GL_ONE);
9360                 }
9361
9362                 // copy the vertically blurred bloom view to a texture
9363                 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);
9364                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9365         }
9366 }
9367
9368 void R_HDR_RenderBloomTexture(void)
9369 {
9370         int oldwidth, oldheight;
9371         float oldcolorscale;
9372         qboolean oldwaterstate;
9373
9374         oldwaterstate = r_waterstate.enabled;
9375         oldcolorscale = r_refdef.view.colorscale;
9376         oldwidth = r_refdef.view.width;
9377         oldheight = r_refdef.view.height;
9378         r_refdef.view.width = r_bloomstate.bloomwidth;
9379         r_refdef.view.height = r_bloomstate.bloomheight;
9380
9381         if(r_hdr.integer < 2)
9382                 r_waterstate.enabled = false;
9383
9384         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9385         // TODO: add exposure compensation features
9386         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9387
9388         r_refdef.view.showdebug = false;
9389         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9390
9391         R_ResetViewRendering3D();
9392
9393         R_ClearScreen(r_refdef.fogenabled);
9394         if (r_timereport_active)
9395                 R_TimeReport("HDRclear");
9396
9397         R_View_Update();
9398         if (r_timereport_active)
9399                 R_TimeReport("visibility");
9400
9401         // only do secondary renders with HDR if r_hdr is 2 or higher
9402         r_waterstate.numwaterplanes = 0;
9403         if (r_waterstate.enabled)
9404                 R_RenderWaterPlanes();
9405
9406         r_refdef.view.showdebug = true;
9407         R_RenderScene();
9408         r_waterstate.numwaterplanes = 0;
9409
9410         R_ResetViewRendering2D();
9411
9412         R_Bloom_CopyHDRTexture();
9413         R_Bloom_MakeTexture();
9414
9415         // restore the view settings
9416         r_waterstate.enabled = oldwaterstate;
9417         r_refdef.view.width = oldwidth;
9418         r_refdef.view.height = oldheight;
9419         r_refdef.view.colorscale = oldcolorscale;
9420
9421         R_ResetViewRendering3D();
9422
9423         R_ClearScreen(r_refdef.fogenabled);
9424         if (r_timereport_active)
9425                 R_TimeReport("viewclear");
9426 }
9427
9428 static void R_BlendView(void)
9429 {
9430         unsigned int permutation;
9431         float uservecs[4][4];
9432
9433         switch (vid.renderpath)
9434         {
9435         case RENDERPATH_GL20:
9436         case RENDERPATH_CGGL:
9437         case RENDERPATH_D3D9:
9438         case RENDERPATH_D3D10:
9439         case RENDERPATH_D3D11:
9440         case RENDERPATH_SOFT:
9441         case RENDERPATH_GLES2:
9442                 permutation =
9443                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9444                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9445                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9446                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9447                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9448
9449                 if (r_bloomstate.texture_screen)
9450                 {
9451                         // make sure the buffer is available
9452                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9453
9454                         R_ResetViewRendering2D();
9455
9456                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9457                         {
9458                                 // declare variables
9459                                 float speed;
9460                                 static float avgspeed;
9461
9462                                 speed = VectorLength(cl.movement_velocity);
9463
9464                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9465                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9466
9467                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9468                                 speed = bound(0, speed, 1);
9469                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9470
9471                                 // calculate values into a standard alpha
9472                                 cl.motionbluralpha = 1 - exp(-
9473                                                 (
9474                                                  (r_motionblur.value * speed / 80)
9475                                                  +
9476                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9477                                                 )
9478                                                 /
9479                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9480                                            );
9481
9482                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9483                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9484                                 // apply the blur
9485                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9486                                 {
9487                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9488                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9489                                         switch(vid.renderpath)
9490                                         {
9491                                         case RENDERPATH_GL11:
9492                                         case RENDERPATH_GL13:
9493                                         case RENDERPATH_GL20:
9494                                         case RENDERPATH_CGGL:
9495                                         case RENDERPATH_SOFT:
9496                                         case RENDERPATH_GLES2:
9497                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9498                                                 break;
9499                                         case RENDERPATH_D3D9:
9500                                         case RENDERPATH_D3D10:
9501                                         case RENDERPATH_D3D11:
9502                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9503                                                 break;
9504                                         }
9505                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9506                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9507                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9508                                 }
9509                         }
9510
9511                         // copy view into the screen texture
9512                         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);
9513                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9514                 }
9515                 else if (!r_bloomstate.texture_bloom)
9516                 {
9517                         // we may still have to do view tint...
9518                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9519                         {
9520                                 // apply a color tint to the whole view
9521                                 R_ResetViewRendering2D();
9522                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9523                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9524                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9525                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9526                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9527                         }
9528                         break; // no screen processing, no bloom, skip it
9529                 }
9530
9531                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9532                 {
9533                         // render simple bloom effect
9534                         // copy the screen and shrink it and darken it for the bloom process
9535                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9536                         // make the bloom texture
9537                         R_Bloom_MakeTexture();
9538                 }
9539
9540 #if _MSC_VER >= 1400
9541 #define sscanf sscanf_s
9542 #endif
9543                 memset(uservecs, 0, sizeof(uservecs));
9544                 if (r_glsl_postprocess_uservec1_enable.integer)
9545                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9546                 if (r_glsl_postprocess_uservec2_enable.integer)
9547                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9548                 if (r_glsl_postprocess_uservec3_enable.integer)
9549                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9550                 if (r_glsl_postprocess_uservec4_enable.integer)
9551                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9552
9553                 R_ResetViewRendering2D();
9554                 GL_Color(1, 1, 1, 1);
9555                 GL_BlendFunc(GL_ONE, GL_ZERO);
9556
9557                 switch(vid.renderpath)
9558                 {
9559                 case RENDERPATH_GL20:
9560                 case RENDERPATH_GLES2:
9561                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9562                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9563                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
9564                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
9565                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
9566                         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]);
9567                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9568                         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]);
9569                         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]);
9570                         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]);
9571                         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]);
9572                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9573                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9574                         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);
9575                         break;
9576                 case RENDERPATH_CGGL:
9577 #ifdef SUPPORTCG
9578                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9579                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9580                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9581                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9582                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9583                         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
9584                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9585                         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
9586                         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
9587                         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
9588                         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
9589                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9590                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9591                         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);
9592 #endif
9593                         break;
9594                 case RENDERPATH_D3D9:
9595 #ifdef SUPPORTD3D
9596                         // 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...
9597                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9598                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9599                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9600                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9601                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9602                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9603                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9604                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9605                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9606                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9607                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9608                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9609                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9610                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9611 #endif
9612                         break;
9613                 case RENDERPATH_D3D10:
9614                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9615                         break;
9616                 case RENDERPATH_D3D11:
9617                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9618                         break;
9619                 case RENDERPATH_SOFT:
9620                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9621                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
9622                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9623                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9624                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9625                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9626                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9627                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9628                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9629                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9630                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9631                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
9632                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9633                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9634                         break;
9635                 default:
9636                         break;
9637                 }
9638                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9639                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9640                 break;
9641         case RENDERPATH_GL13:
9642         case RENDERPATH_GL11:
9643                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9644                 {
9645                         // apply a color tint to the whole view
9646                         R_ResetViewRendering2D();
9647                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9648                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9649                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9650                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9651                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9652                 }
9653                 break;
9654         }
9655 }
9656
9657 matrix4x4_t r_waterscrollmatrix;
9658
9659 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9660 {
9661         if (r_refdef.fog_density)
9662         {
9663                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9664                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9665                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9666
9667                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9668                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9669                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9670                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9671
9672                 {
9673                         vec3_t fogvec;
9674                         VectorCopy(r_refdef.fogcolor, fogvec);
9675                         //   color.rgb *= ContrastBoost * SceneBrightness;
9676                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9677                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9678                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9679                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9680                 }
9681         }
9682 }
9683
9684 void R_UpdateVariables(void)
9685 {
9686         R_Textures_Frame();
9687
9688         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9689
9690         r_refdef.farclip = r_farclip_base.value;
9691         if (r_refdef.scene.worldmodel)
9692                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9693         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9694
9695         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9696                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9697         r_refdef.polygonfactor = 0;
9698         r_refdef.polygonoffset = 0;
9699         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9700         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9701
9702         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9703         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9704         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
9705         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9706         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9707         if (FAKELIGHT_ENABLED)
9708         {
9709                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9710         }
9711         if (r_showsurfaces.integer)
9712         {
9713                 r_refdef.scene.rtworld = false;
9714                 r_refdef.scene.rtworldshadows = false;
9715                 r_refdef.scene.rtdlight = false;
9716                 r_refdef.scene.rtdlightshadows = false;
9717                 r_refdef.lightmapintensity = 0;
9718         }
9719
9720         if (gamemode == GAME_NEHAHRA)
9721         {
9722                 if (gl_fogenable.integer)
9723                 {
9724                         r_refdef.oldgl_fogenable = true;
9725                         r_refdef.fog_density = gl_fogdensity.value;
9726                         r_refdef.fog_red = gl_fogred.value;
9727                         r_refdef.fog_green = gl_foggreen.value;
9728                         r_refdef.fog_blue = gl_fogblue.value;
9729                         r_refdef.fog_alpha = 1;
9730                         r_refdef.fog_start = 0;
9731                         r_refdef.fog_end = gl_skyclip.value;
9732                         r_refdef.fog_height = 1<<30;
9733                         r_refdef.fog_fadedepth = 128;
9734                 }
9735                 else if (r_refdef.oldgl_fogenable)
9736                 {
9737                         r_refdef.oldgl_fogenable = false;
9738                         r_refdef.fog_density = 0;
9739                         r_refdef.fog_red = 0;
9740                         r_refdef.fog_green = 0;
9741                         r_refdef.fog_blue = 0;
9742                         r_refdef.fog_alpha = 0;
9743                         r_refdef.fog_start = 0;
9744                         r_refdef.fog_end = 0;
9745                         r_refdef.fog_height = 1<<30;
9746                         r_refdef.fog_fadedepth = 128;
9747                 }
9748         }
9749
9750         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9751         r_refdef.fog_start = max(0, r_refdef.fog_start);
9752         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9753
9754         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9755
9756         if (r_refdef.fog_density && r_drawfog.integer)
9757         {
9758                 r_refdef.fogenabled = true;
9759                 // this is the point where the fog reaches 0.9986 alpha, which we
9760                 // consider a good enough cutoff point for the texture
9761                 // (0.9986 * 256 == 255.6)
9762                 if (r_fog_exp2.integer)
9763                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9764                 else
9765                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9766                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9767                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9768                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9769                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9770                         R_BuildFogHeightTexture();
9771                 // fog color was already set
9772                 // update the fog texture
9773                 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)
9774                         R_BuildFogTexture();
9775                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9776                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9777         }
9778         else
9779                 r_refdef.fogenabled = false;
9780
9781         switch(vid.renderpath)
9782         {
9783         case RENDERPATH_GL20:
9784         case RENDERPATH_CGGL:
9785         case RENDERPATH_D3D9:
9786         case RENDERPATH_D3D10:
9787         case RENDERPATH_D3D11:
9788         case RENDERPATH_SOFT:
9789         case RENDERPATH_GLES2:
9790                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9791                 {
9792                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9793                         {
9794                                 // build GLSL gamma texture
9795 #define RAMPWIDTH 256
9796                                 unsigned short ramp[RAMPWIDTH * 3];
9797                                 unsigned char rampbgr[RAMPWIDTH][4];
9798                                 int i;
9799
9800                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9801
9802                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9803                                 for(i = 0; i < RAMPWIDTH; ++i)
9804                                 {
9805                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9806                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9807                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9808                                         rampbgr[i][3] = 0;
9809                                 }
9810                                 if (r_texture_gammaramps)
9811                                 {
9812                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9813                                 }
9814                                 else
9815                                 {
9816                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9817                                 }
9818                         }
9819                 }
9820                 else
9821                 {
9822                         // remove GLSL gamma texture
9823                 }
9824                 break;
9825         case RENDERPATH_GL13:
9826         case RENDERPATH_GL11:
9827                 break;
9828         }
9829 }
9830
9831 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9832 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9833 /*
9834 ================
9835 R_SelectScene
9836 ================
9837 */
9838 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9839         if( scenetype != r_currentscenetype ) {
9840                 // store the old scenetype
9841                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9842                 r_currentscenetype = scenetype;
9843                 // move in the new scene
9844                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9845         }
9846 }
9847
9848 /*
9849 ================
9850 R_GetScenePointer
9851 ================
9852 */
9853 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9854 {
9855         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9856         if( scenetype == r_currentscenetype ) {
9857                 return &r_refdef.scene;
9858         } else {
9859                 return &r_scenes_store[ scenetype ];
9860         }
9861 }
9862
9863 /*
9864 ================
9865 R_RenderView
9866 ================
9867 */
9868 int dpsoftrast_test;
9869 void R_RenderView(void)
9870 {
9871         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9872
9873         dpsoftrast_test = r_test.integer;
9874
9875         if (r_timereport_active)
9876                 R_TimeReport("start");
9877         r_textureframe++; // used only by R_GetCurrentTexture
9878         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9879
9880         if(R_CompileShader_CheckStaticParms())
9881                 R_GLSL_Restart_f();
9882
9883         if (!r_drawentities.integer)
9884                 r_refdef.scene.numentities = 0;
9885
9886         R_AnimCache_ClearCache();
9887         R_FrameData_NewFrame();
9888
9889         /* adjust for stereo display */
9890         if(R_Stereo_Active())
9891         {
9892                 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);
9893                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9894         }
9895
9896         if (r_refdef.view.isoverlay)
9897         {
9898                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9899                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9900                 R_TimeReport("depthclear");
9901
9902                 r_refdef.view.showdebug = false;
9903
9904                 r_waterstate.enabled = false;
9905                 r_waterstate.numwaterplanes = 0;
9906
9907                 R_RenderScene();
9908
9909                 r_refdef.view.matrix = originalmatrix;
9910
9911                 CHECKGLERROR
9912                 return;
9913         }
9914
9915         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9916         {
9917                 r_refdef.view.matrix = originalmatrix;
9918                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9919         }
9920
9921         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9922
9923         R_RenderView_UpdateViewVectors();
9924
9925         R_Shadow_UpdateWorldLightSelection();
9926
9927         R_Bloom_StartFrame();
9928         R_Water_StartFrame();
9929
9930         CHECKGLERROR
9931         if (r_timereport_active)
9932                 R_TimeReport("viewsetup");
9933
9934         R_ResetViewRendering3D();
9935
9936         if (r_refdef.view.clear || r_refdef.fogenabled)
9937         {
9938                 R_ClearScreen(r_refdef.fogenabled);
9939                 if (r_timereport_active)
9940                         R_TimeReport("viewclear");
9941         }
9942         r_refdef.view.clear = true;
9943
9944         // this produces a bloom texture to be used in R_BlendView() later
9945         if (r_hdr.integer && r_bloomstate.bloomwidth)
9946         {
9947                 R_HDR_RenderBloomTexture();
9948                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9949                 r_textureframe++; // used only by R_GetCurrentTexture
9950         }
9951
9952         r_refdef.view.showdebug = true;
9953
9954         R_View_Update();
9955         if (r_timereport_active)
9956                 R_TimeReport("visibility");
9957
9958         r_waterstate.numwaterplanes = 0;
9959         if (r_waterstate.enabled)
9960                 R_RenderWaterPlanes();
9961
9962         R_RenderScene();
9963         r_waterstate.numwaterplanes = 0;
9964
9965         R_BlendView();
9966         if (r_timereport_active)
9967                 R_TimeReport("blendview");
9968
9969         GL_Scissor(0, 0, vid.width, vid.height);
9970         GL_ScissorTest(false);
9971
9972         r_refdef.view.matrix = originalmatrix;
9973
9974         CHECKGLERROR
9975 }
9976
9977 void R_RenderWaterPlanes(void)
9978 {
9979         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9980         {
9981                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9982                 if (r_timereport_active)
9983                         R_TimeReport("waterworld");
9984         }
9985
9986         // don't let sound skip if going slow
9987         if (r_refdef.scene.extraupdate)
9988                 S_ExtraUpdate ();
9989
9990         R_DrawModelsAddWaterPlanes();
9991         if (r_timereport_active)
9992                 R_TimeReport("watermodels");
9993
9994         if (r_waterstate.numwaterplanes)
9995         {
9996                 R_Water_ProcessPlanes();
9997                 if (r_timereport_active)
9998                         R_TimeReport("waterscenes");
9999         }
10000 }
10001
10002 extern void R_DrawLightningBeams (void);
10003 extern void VM_CL_AddPolygonsToMeshQueue (void);
10004 extern void R_DrawPortals (void);
10005 extern cvar_t cl_locs_show;
10006 static void R_DrawLocs(void);
10007 static void R_DrawEntityBBoxes(void);
10008 static void R_DrawModelDecals(void);
10009 extern void R_DrawModelShadows(void);
10010 extern void R_DrawModelShadowMaps(void);
10011 extern cvar_t cl_decals_newsystem;
10012 extern qboolean r_shadow_usingdeferredprepass;
10013 void R_RenderScene(void)
10014 {
10015         qboolean shadowmapping = false;
10016
10017         if (r_timereport_active)
10018                 R_TimeReport("beginscene");
10019
10020         r_refdef.stats.renders++;
10021
10022         R_UpdateFogColor();
10023
10024         // don't let sound skip if going slow
10025         if (r_refdef.scene.extraupdate)
10026                 S_ExtraUpdate ();
10027
10028         R_MeshQueue_BeginScene();
10029
10030         R_SkyStartFrame();
10031
10032         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);
10033
10034         if (r_timereport_active)
10035                 R_TimeReport("skystartframe");
10036
10037         if (cl.csqc_vidvars.drawworld)
10038         {
10039                 // don't let sound skip if going slow
10040                 if (r_refdef.scene.extraupdate)
10041                         S_ExtraUpdate ();
10042
10043                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
10044                 {
10045                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
10046                         if (r_timereport_active)
10047                                 R_TimeReport("worldsky");
10048                 }
10049
10050                 if (R_DrawBrushModelsSky() && r_timereport_active)
10051                         R_TimeReport("bmodelsky");
10052
10053                 if (skyrendermasked && skyrenderlater)
10054                 {
10055                         // we have to force off the water clipping plane while rendering sky
10056                         R_SetupView(false);
10057                         R_Sky();
10058                         R_SetupView(true);
10059                         if (r_timereport_active)
10060                                 R_TimeReport("sky");
10061                 }
10062         }
10063
10064         R_AnimCache_CacheVisibleEntities();
10065         if (r_timereport_active)
10066                 R_TimeReport("animation");
10067
10068         R_Shadow_PrepareLights();
10069         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
10070                 R_Shadow_PrepareModelShadows();
10071         if (r_timereport_active)
10072                 R_TimeReport("preparelights");
10073
10074         if (R_Shadow_ShadowMappingEnabled())
10075                 shadowmapping = true;
10076
10077         if (r_shadow_usingdeferredprepass)
10078                 R_Shadow_DrawPrepass();
10079
10080         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
10081         {
10082                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
10083                 if (r_timereport_active)
10084                         R_TimeReport("worlddepth");
10085         }
10086         if (r_depthfirst.integer >= 2)
10087         {
10088                 R_DrawModelsDepth();
10089                 if (r_timereport_active)
10090                         R_TimeReport("modeldepth");
10091         }
10092
10093         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
10094         {
10095                 R_DrawModelShadowMaps();
10096                 R_ResetViewRendering3D();
10097                 // don't let sound skip if going slow
10098                 if (r_refdef.scene.extraupdate)
10099                         S_ExtraUpdate ();
10100         }
10101
10102         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
10103         {
10104                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
10105                 if (r_timereport_active)
10106                         R_TimeReport("world");
10107         }
10108
10109         // don't let sound skip if going slow
10110         if (r_refdef.scene.extraupdate)
10111                 S_ExtraUpdate ();
10112
10113         R_DrawModels();
10114         if (r_timereport_active)
10115                 R_TimeReport("models");
10116
10117         // don't let sound skip if going slow
10118         if (r_refdef.scene.extraupdate)
10119                 S_ExtraUpdate ();
10120
10121         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
10122         {
10123                 R_DrawModelShadows();
10124                 R_ResetViewRendering3D();
10125                 // don't let sound skip if going slow
10126                 if (r_refdef.scene.extraupdate)
10127                         S_ExtraUpdate ();
10128         }
10129
10130         if (!r_shadow_usingdeferredprepass)
10131         {
10132                 R_Shadow_DrawLights();
10133                 if (r_timereport_active)
10134                         R_TimeReport("rtlights");
10135         }
10136
10137         // don't let sound skip if going slow
10138         if (r_refdef.scene.extraupdate)
10139                 S_ExtraUpdate ();
10140
10141         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
10142         {
10143                 R_DrawModelShadows();
10144                 R_ResetViewRendering3D();
10145                 // don't let sound skip if going slow
10146                 if (r_refdef.scene.extraupdate)
10147                         S_ExtraUpdate ();
10148         }
10149
10150         if (cl.csqc_vidvars.drawworld)
10151         {
10152                 if (cl_decals_newsystem.integer)
10153                 {
10154                         R_DrawModelDecals();
10155                         if (r_timereport_active)
10156                                 R_TimeReport("modeldecals");
10157                 }
10158                 else
10159                 {
10160                         R_DrawDecals();
10161                         if (r_timereport_active)
10162                                 R_TimeReport("decals");
10163                 }
10164
10165                 R_DrawParticles();
10166                 if (r_timereport_active)
10167                         R_TimeReport("particles");
10168
10169                 R_DrawExplosions();
10170                 if (r_timereport_active)
10171                         R_TimeReport("explosions");
10172
10173                 R_DrawLightningBeams();
10174                 if (r_timereport_active)
10175                         R_TimeReport("lightning");
10176         }
10177
10178         VM_CL_AddPolygonsToMeshQueue();
10179
10180         if (r_refdef.view.showdebug)
10181         {
10182                 if (cl_locs_show.integer)
10183                 {
10184                         R_DrawLocs();
10185                         if (r_timereport_active)
10186                                 R_TimeReport("showlocs");
10187                 }
10188
10189                 if (r_drawportals.integer)
10190                 {
10191                         R_DrawPortals();
10192                         if (r_timereport_active)
10193                                 R_TimeReport("portals");
10194                 }
10195
10196                 if (r_showbboxes.value > 0)
10197                 {
10198                         R_DrawEntityBBoxes();
10199                         if (r_timereport_active)
10200                                 R_TimeReport("bboxes");
10201                 }
10202         }
10203
10204         R_MeshQueue_RenderTransparent();
10205         if (r_timereport_active)
10206                 R_TimeReport("drawtrans");
10207
10208         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))
10209         {
10210                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
10211                 if (r_timereport_active)
10212                         R_TimeReport("worlddebug");
10213                 R_DrawModelsDebug();
10214                 if (r_timereport_active)
10215                         R_TimeReport("modeldebug");
10216         }
10217
10218         if (cl.csqc_vidvars.drawworld)
10219         {
10220                 R_Shadow_DrawCoronas();
10221                 if (r_timereport_active)
10222                         R_TimeReport("coronas");
10223         }
10224
10225 #if 0
10226         {
10227                 GL_DepthTest(false);
10228                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10229                 GL_Color(1, 1, 1, 1);
10230                 qglBegin(GL_POLYGON);
10231                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
10232                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
10233                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
10234                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
10235                 qglEnd();
10236                 qglBegin(GL_POLYGON);
10237                 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]);
10238                 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]);
10239                 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]);
10240                 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]);
10241                 qglEnd();
10242                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10243         }
10244 #endif
10245
10246         // don't let sound skip if going slow
10247         if (r_refdef.scene.extraupdate)
10248                 S_ExtraUpdate ();
10249
10250         R_ResetViewRendering2D();
10251 }
10252
10253 static const unsigned short bboxelements[36] =
10254 {
10255         5, 1, 3, 5, 3, 7,
10256         6, 2, 0, 6, 0, 4,
10257         7, 3, 2, 7, 2, 6,
10258         4, 0, 1, 4, 1, 5,
10259         4, 5, 7, 4, 7, 6,
10260         1, 0, 2, 1, 2, 3,
10261 };
10262
10263 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
10264 {
10265         int i;
10266         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
10267
10268         RSurf_ActiveWorldEntity();
10269
10270         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10271         GL_DepthMask(false);
10272         GL_DepthRange(0, 1);
10273         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10274 //      R_Mesh_ResetTextureState();
10275
10276         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
10277         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
10278         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
10279         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
10280         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
10281         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
10282         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
10283         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
10284         R_FillColors(color4f, 8, cr, cg, cb, ca);
10285         if (r_refdef.fogenabled)
10286         {
10287                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
10288                 {
10289                         f1 = RSurf_FogVertex(v);
10290                         f2 = 1 - f1;
10291                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10292                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10293                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10294                 }
10295         }
10296         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10297         R_Mesh_ResetTextureState();
10298         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10299         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10300 }
10301
10302 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10303 {
10304         int i;
10305         float color[4];
10306         prvm_edict_t *edict;
10307         prvm_prog_t *prog_save = prog;
10308
10309         // this function draws bounding boxes of server entities
10310         if (!sv.active)
10311                 return;
10312
10313         GL_CullFace(GL_NONE);
10314         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10315
10316         prog = 0;
10317         SV_VM_Begin();
10318         for (i = 0;i < numsurfaces;i++)
10319         {
10320                 edict = PRVM_EDICT_NUM(surfacelist[i]);
10321                 switch ((int)edict->fields.server->solid)
10322                 {
10323                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
10324                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
10325                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
10326                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10327                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
10328                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
10329                 }
10330                 color[3] *= r_showbboxes.value;
10331                 color[3] = bound(0, color[3], 1);
10332                 GL_DepthTest(!r_showdisabledepthtest.integer);
10333                 GL_CullFace(r_refdef.view.cullface_front);
10334                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10335         }
10336         SV_VM_End();
10337         prog = prog_save;
10338 }
10339
10340 static void R_DrawEntityBBoxes(void)
10341 {
10342         int i;
10343         prvm_edict_t *edict;
10344         vec3_t center;
10345         prvm_prog_t *prog_save = prog;
10346
10347         // this function draws bounding boxes of server entities
10348         if (!sv.active)
10349                 return;
10350
10351         prog = 0;
10352         SV_VM_Begin();
10353         for (i = 0;i < prog->num_edicts;i++)
10354         {
10355                 edict = PRVM_EDICT_NUM(i);
10356                 if (edict->priv.server->free)
10357                         continue;
10358                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10359                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10360                         continue;
10361                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10362                         continue;
10363                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10364                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10365         }
10366         SV_VM_End();
10367         prog = prog_save;
10368 }
10369
10370 static const int nomodelelement3i[24] =
10371 {
10372         5, 2, 0,
10373         5, 1, 2,
10374         5, 0, 3,
10375         5, 3, 1,
10376         0, 2, 4,
10377         2, 1, 4,
10378         3, 0, 4,
10379         1, 3, 4
10380 };
10381
10382 static const unsigned short nomodelelement3s[24] =
10383 {
10384         5, 2, 0,
10385         5, 1, 2,
10386         5, 0, 3,
10387         5, 3, 1,
10388         0, 2, 4,
10389         2, 1, 4,
10390         3, 0, 4,
10391         1, 3, 4
10392 };
10393
10394 static const float nomodelvertex3f[6*3] =
10395 {
10396         -16,   0,   0,
10397          16,   0,   0,
10398           0, -16,   0,
10399           0,  16,   0,
10400           0,   0, -16,
10401           0,   0,  16
10402 };
10403
10404 static const float nomodelcolor4f[6*4] =
10405 {
10406         0.0f, 0.0f, 0.5f, 1.0f,
10407         0.0f, 0.0f, 0.5f, 1.0f,
10408         0.0f, 0.5f, 0.0f, 1.0f,
10409         0.0f, 0.5f, 0.0f, 1.0f,
10410         0.5f, 0.0f, 0.0f, 1.0f,
10411         0.5f, 0.0f, 0.0f, 1.0f
10412 };
10413
10414 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10415 {
10416         int i;
10417         float f1, f2, *c;
10418         float color4f[6*4];
10419
10420         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);
10421
10422         // this is only called once per entity so numsurfaces is always 1, and
10423         // surfacelist is always {0}, so this code does not handle batches
10424
10425         if (rsurface.ent_flags & RENDER_ADDITIVE)
10426         {
10427                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10428                 GL_DepthMask(false);
10429         }
10430         else if (rsurface.colormod[3] < 1)
10431         {
10432                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10433                 GL_DepthMask(false);
10434         }
10435         else
10436         {
10437                 GL_BlendFunc(GL_ONE, GL_ZERO);
10438                 GL_DepthMask(true);
10439         }
10440         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10441         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10442         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10443         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10444         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10445         for (i = 0, c = color4f;i < 6;i++, c += 4)
10446         {
10447                 c[0] *= rsurface.colormod[0];
10448                 c[1] *= rsurface.colormod[1];
10449                 c[2] *= rsurface.colormod[2];
10450                 c[3] *= rsurface.colormod[3];
10451         }
10452         if (r_refdef.fogenabled)
10453         {
10454                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10455                 {
10456                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10457                         f2 = 1 - f1;
10458                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10459                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10460                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10461                 }
10462         }
10463 //      R_Mesh_ResetTextureState();
10464         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10465         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10466         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10467 }
10468
10469 void R_DrawNoModel(entity_render_t *ent)
10470 {
10471         vec3_t org;
10472         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10473         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10474                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10475         else
10476                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10477 }
10478
10479 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10480 {
10481         vec3_t right1, right2, diff, normal;
10482
10483         VectorSubtract (org2, org1, normal);
10484
10485         // calculate 'right' vector for start
10486         VectorSubtract (r_refdef.view.origin, org1, diff);
10487         CrossProduct (normal, diff, right1);
10488         VectorNormalize (right1);
10489
10490         // calculate 'right' vector for end
10491         VectorSubtract (r_refdef.view.origin, org2, diff);
10492         CrossProduct (normal, diff, right2);
10493         VectorNormalize (right2);
10494
10495         vert[ 0] = org1[0] + width * right1[0];
10496         vert[ 1] = org1[1] + width * right1[1];
10497         vert[ 2] = org1[2] + width * right1[2];
10498         vert[ 3] = org1[0] - width * right1[0];
10499         vert[ 4] = org1[1] - width * right1[1];
10500         vert[ 5] = org1[2] - width * right1[2];
10501         vert[ 6] = org2[0] - width * right2[0];
10502         vert[ 7] = org2[1] - width * right2[1];
10503         vert[ 8] = org2[2] - width * right2[2];
10504         vert[ 9] = org2[0] + width * right2[0];
10505         vert[10] = org2[1] + width * right2[1];
10506         vert[11] = org2[2] + width * right2[2];
10507 }
10508
10509 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)
10510 {
10511         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10512         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10513         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10514         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10515         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10516         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10517         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10518         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10519         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10520         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10521         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10522         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10523 }
10524
10525 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10526 {
10527         int i;
10528         float *vertex3f;
10529         float v[3];
10530         VectorSet(v, x, y, z);
10531         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10532                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10533                         break;
10534         if (i == mesh->numvertices)
10535         {
10536                 if (mesh->numvertices < mesh->maxvertices)
10537                 {
10538                         VectorCopy(v, vertex3f);
10539                         mesh->numvertices++;
10540                 }
10541                 return mesh->numvertices;
10542         }
10543         else
10544                 return i;
10545 }
10546
10547 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10548 {
10549         int i;
10550         int *e, element[3];
10551         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10552         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10553         e = mesh->element3i + mesh->numtriangles * 3;
10554         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10555         {
10556                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10557                 if (mesh->numtriangles < mesh->maxtriangles)
10558                 {
10559                         *e++ = element[0];
10560                         *e++ = element[1];
10561                         *e++ = element[2];
10562                         mesh->numtriangles++;
10563                 }
10564                 element[1] = element[2];
10565         }
10566 }
10567
10568 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10569 {
10570         int i;
10571         int *e, element[3];
10572         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10573         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10574         e = mesh->element3i + mesh->numtriangles * 3;
10575         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10576         {
10577                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10578                 if (mesh->numtriangles < mesh->maxtriangles)
10579                 {
10580                         *e++ = element[0];
10581                         *e++ = element[1];
10582                         *e++ = element[2];
10583                         mesh->numtriangles++;
10584                 }
10585                 element[1] = element[2];
10586         }
10587 }
10588
10589 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10590 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10591 {
10592         int planenum, planenum2;
10593         int w;
10594         int tempnumpoints;
10595         mplane_t *plane, *plane2;
10596         double maxdist;
10597         double temppoints[2][256*3];
10598         // figure out how large a bounding box we need to properly compute this brush
10599         maxdist = 0;
10600         for (w = 0;w < numplanes;w++)
10601                 maxdist = max(maxdist, fabs(planes[w].dist));
10602         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10603         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10604         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10605         {
10606                 w = 0;
10607                 tempnumpoints = 4;
10608                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10609                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10610                 {
10611                         if (planenum2 == planenum)
10612                                 continue;
10613                         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);
10614                         w = !w;
10615                 }
10616                 if (tempnumpoints < 3)
10617                         continue;
10618                 // generate elements forming a triangle fan for this polygon
10619                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10620         }
10621 }
10622
10623 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)
10624 {
10625         texturelayer_t *layer;
10626         layer = t->currentlayers + t->currentnumlayers++;
10627         layer->type = type;
10628         layer->depthmask = depthmask;
10629         layer->blendfunc1 = blendfunc1;
10630         layer->blendfunc2 = blendfunc2;
10631         layer->texture = texture;
10632         layer->texmatrix = *matrix;
10633         layer->color[0] = r;
10634         layer->color[1] = g;
10635         layer->color[2] = b;
10636         layer->color[3] = a;
10637 }
10638
10639 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10640 {
10641         if(parms[0] == 0 && parms[1] == 0)
10642                 return false;
10643         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10644                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10645                         return false;
10646         return true;
10647 }
10648
10649 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10650 {
10651         double index, f;
10652         index = parms[2] + r_refdef.scene.time * parms[3];
10653         index -= floor(index);
10654         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10655         {
10656         default:
10657         case Q3WAVEFUNC_NONE:
10658         case Q3WAVEFUNC_NOISE:
10659         case Q3WAVEFUNC_COUNT:
10660                 f = 0;
10661                 break;
10662         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10663         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10664         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10665         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10666         case Q3WAVEFUNC_TRIANGLE:
10667                 index *= 4;
10668                 f = index - floor(index);
10669                 if (index < 1)
10670                         f = f;
10671                 else if (index < 2)
10672                         f = 1 - f;
10673                 else if (index < 3)
10674                         f = -f;
10675                 else
10676                         f = -(1 - f);
10677                 break;
10678         }
10679         f = parms[0] + parms[1] * f;
10680         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10681                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10682         return (float) f;
10683 }
10684
10685 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10686 {
10687         int w, h, idx;
10688         float f;
10689         float tcmat[12];
10690         matrix4x4_t matrix, temp;
10691         switch(tcmod->tcmod)
10692         {
10693                 case Q3TCMOD_COUNT:
10694                 case Q3TCMOD_NONE:
10695                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10696                                 matrix = r_waterscrollmatrix;
10697                         else
10698                                 matrix = identitymatrix;
10699                         break;
10700                 case Q3TCMOD_ENTITYTRANSLATE:
10701                         // this is used in Q3 to allow the gamecode to control texcoord
10702                         // scrolling on the entity, which is not supported in darkplaces yet.
10703                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10704                         break;
10705                 case Q3TCMOD_ROTATE:
10706                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10707                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10708                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10709                         break;
10710                 case Q3TCMOD_SCALE:
10711                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10712                         break;
10713                 case Q3TCMOD_SCROLL:
10714                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10715                         break;
10716                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10717                         w = (int) tcmod->parms[0];
10718                         h = (int) tcmod->parms[1];
10719                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10720                         f = f - floor(f);
10721                         idx = (int) floor(f * w * h);
10722                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10723                         break;
10724                 case Q3TCMOD_STRETCH:
10725                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10726                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10727                         break;
10728                 case Q3TCMOD_TRANSFORM:
10729                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10730                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10731                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10732                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10733                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10734                         break;
10735                 case Q3TCMOD_TURBULENT:
10736                         // this is handled in the RSurf_PrepareVertices function
10737                         matrix = identitymatrix;
10738                         break;
10739         }
10740         temp = *texmatrix;
10741         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10742 }
10743
10744 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10745 {
10746         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10747         char name[MAX_QPATH];
10748         skinframe_t *skinframe;
10749         unsigned char pixels[296*194];
10750         strlcpy(cache->name, skinname, sizeof(cache->name));
10751         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10752         if (developer_loading.integer)
10753                 Con_Printf("loading %s\n", name);
10754         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10755         if (!skinframe || !skinframe->base)
10756         {
10757                 unsigned char *f;
10758                 fs_offset_t filesize;
10759                 skinframe = NULL;
10760                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10761                 if (f)
10762                 {
10763                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10764                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10765                         Mem_Free(f);
10766                 }
10767         }
10768         cache->skinframe = skinframe;
10769 }
10770
10771 texture_t *R_GetCurrentTexture(texture_t *t)
10772 {
10773         int i;
10774         const entity_render_t *ent = rsurface.entity;
10775         dp_model_t *model = ent->model;
10776         q3shaderinfo_layer_tcmod_t *tcmod;
10777
10778         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10779                 return t->currentframe;
10780         t->update_lastrenderframe = r_textureframe;
10781         t->update_lastrenderentity = (void *)ent;
10782
10783         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10784                 t->camera_entity = ent->entitynumber;
10785         else
10786                 t->camera_entity = 0;
10787
10788         // switch to an alternate material if this is a q1bsp animated material
10789         {
10790                 texture_t *texture = t;
10791                 int s = rsurface.ent_skinnum;
10792                 if ((unsigned int)s >= (unsigned int)model->numskins)
10793                         s = 0;
10794                 if (model->skinscenes)
10795                 {
10796                         if (model->skinscenes[s].framecount > 1)
10797                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10798                         else
10799                                 s = model->skinscenes[s].firstframe;
10800                 }
10801                 if (s > 0)
10802                         t = t + s * model->num_surfaces;
10803                 if (t->animated)
10804                 {
10805                         // use an alternate animation if the entity's frame is not 0,
10806                         // and only if the texture has an alternate animation
10807                         if (rsurface.ent_alttextures && t->anim_total[1])
10808                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10809                         else
10810                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10811                 }
10812                 texture->currentframe = t;
10813         }
10814
10815         // update currentskinframe to be a qw skin or animation frame
10816         if (rsurface.ent_qwskin >= 0)
10817         {
10818                 i = rsurface.ent_qwskin;
10819                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10820                 {
10821                         r_qwskincache_size = cl.maxclients;
10822                         if (r_qwskincache)
10823                                 Mem_Free(r_qwskincache);
10824                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10825                 }
10826                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10827                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10828                 t->currentskinframe = r_qwskincache[i].skinframe;
10829                 if (t->currentskinframe == NULL)
10830                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10831         }
10832         else if (t->numskinframes >= 2)
10833                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10834         if (t->backgroundnumskinframes >= 2)
10835                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10836
10837         t->currentmaterialflags = t->basematerialflags;
10838         t->currentalpha = rsurface.colormod[3];
10839         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10840                 t->currentalpha *= r_wateralpha.value;
10841         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10842                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10843         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10844                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10845         if (!(rsurface.ent_flags & RENDER_LIGHT))
10846                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10847         else if (FAKELIGHT_ENABLED)
10848         {
10849                         // no modellight if using fakelight for the map
10850         }
10851         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10852         {
10853                 // pick a model lighting mode
10854                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10855                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10856                 else
10857                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10858         }
10859         if (rsurface.ent_flags & RENDER_ADDITIVE)
10860                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10861         else if (t->currentalpha < 1)
10862                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10863         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10864                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10865         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10866                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10867         if (t->backgroundnumskinframes)
10868                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10869         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10870         {
10871                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10872                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10873         }
10874         else
10875                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10876         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10877                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10878
10879         // there is no tcmod
10880         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10881         {
10882                 t->currenttexmatrix = r_waterscrollmatrix;
10883                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10884         }
10885         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10886         {
10887                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10888                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10889         }
10890
10891         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10892                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10893         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10894                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10895
10896         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10897         if (t->currentskinframe->qpixels)
10898                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10899         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10900         if (!t->basetexture)
10901                 t->basetexture = r_texture_notexture;
10902         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10903         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10904         t->nmaptexture = t->currentskinframe->nmap;
10905         if (!t->nmaptexture)
10906                 t->nmaptexture = r_texture_blanknormalmap;
10907         t->glosstexture = r_texture_black;
10908         t->glowtexture = t->currentskinframe->glow;
10909         t->fogtexture = t->currentskinframe->fog;
10910         t->reflectmasktexture = t->currentskinframe->reflect;
10911         if (t->backgroundnumskinframes)
10912         {
10913                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10914                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10915                 t->backgroundglosstexture = r_texture_black;
10916                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10917                 if (!t->backgroundnmaptexture)
10918                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10919         }
10920         else
10921         {
10922                 t->backgroundbasetexture = r_texture_white;
10923                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10924                 t->backgroundglosstexture = r_texture_black;
10925                 t->backgroundglowtexture = NULL;
10926         }
10927         t->specularpower = r_shadow_glossexponent.value;
10928         // TODO: store reference values for these in the texture?
10929         t->specularscale = 0;
10930         if (r_shadow_gloss.integer > 0)
10931         {
10932                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10933                 {
10934                         if (r_shadow_glossintensity.value > 0)
10935                         {
10936                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10937                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10938                                 t->specularscale = r_shadow_glossintensity.value;
10939                         }
10940                 }
10941                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10942                 {
10943                         t->glosstexture = r_texture_white;
10944                         t->backgroundglosstexture = r_texture_white;
10945                         t->specularscale = r_shadow_gloss2intensity.value;
10946                         t->specularpower = r_shadow_gloss2exponent.value;
10947                 }
10948         }
10949         t->specularscale *= t->specularscalemod;
10950         t->specularpower *= t->specularpowermod;
10951
10952         // lightmaps mode looks bad with dlights using actual texturing, so turn
10953         // off the colormap and glossmap, but leave the normalmap on as it still
10954         // accurately represents the shading involved
10955         if (gl_lightmaps.integer)
10956         {
10957                 t->basetexture = r_texture_grey128;
10958                 t->pantstexture = r_texture_black;
10959                 t->shirttexture = r_texture_black;
10960                 t->nmaptexture = r_texture_blanknormalmap;
10961                 t->glosstexture = r_texture_black;
10962                 t->glowtexture = NULL;
10963                 t->fogtexture = NULL;
10964                 t->reflectmasktexture = NULL;
10965                 t->backgroundbasetexture = NULL;
10966                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10967                 t->backgroundglosstexture = r_texture_black;
10968                 t->backgroundglowtexture = NULL;
10969                 t->specularscale = 0;
10970                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10971         }
10972
10973         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10974         VectorClear(t->dlightcolor);
10975         t->currentnumlayers = 0;
10976         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10977         {
10978                 int blendfunc1, blendfunc2;
10979                 qboolean depthmask;
10980                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10981                 {
10982                         blendfunc1 = GL_SRC_ALPHA;
10983                         blendfunc2 = GL_ONE;
10984                 }
10985                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10986                 {
10987                         blendfunc1 = GL_SRC_ALPHA;
10988                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10989                 }
10990                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10991                 {
10992                         blendfunc1 = t->customblendfunc[0];
10993                         blendfunc2 = t->customblendfunc[1];
10994                 }
10995                 else
10996                 {
10997                         blendfunc1 = GL_ONE;
10998                         blendfunc2 = GL_ZERO;
10999                 }
11000                 // don't colormod evilblend textures
11001                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
11002                         VectorSet(t->lightmapcolor, 1, 1, 1);
11003                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
11004                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11005                 {
11006                         // fullbright is not affected by r_refdef.lightmapintensity
11007                         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]);
11008                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
11009                                 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]);
11010                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
11011                                 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]);
11012                 }
11013                 else
11014                 {
11015                         vec3_t ambientcolor;
11016                         float colorscale;
11017                         // set the color tint used for lights affecting this surface
11018                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
11019                         colorscale = 2;
11020                         // q3bsp has no lightmap updates, so the lightstylevalue that
11021                         // would normally be baked into the lightmap must be
11022                         // applied to the color
11023                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
11024                         if (model->type == mod_brushq3)
11025                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
11026                         colorscale *= r_refdef.lightmapintensity;
11027                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
11028                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
11029                         // basic lit geometry
11030                         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]);
11031                         // add pants/shirt if needed
11032                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
11033                                 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]);
11034                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
11035                                 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]);
11036                         // now add ambient passes if needed
11037                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
11038                         {
11039                                 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]);
11040                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
11041                                         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]);
11042                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
11043                                         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]);
11044                         }
11045                 }
11046                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
11047                         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]);
11048                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
11049                 {
11050                         // if this is opaque use alpha blend which will darken the earlier
11051                         // passes cheaply.
11052                         //
11053                         // if this is an alpha blended material, all the earlier passes
11054                         // were darkened by fog already, so we only need to add the fog
11055                         // color ontop through the fog mask texture
11056                         //
11057                         // if this is an additive blended material, all the earlier passes
11058                         // were darkened by fog already, and we should not add fog color
11059                         // (because the background was not darkened, there is no fog color
11060                         // that was lost behind it).
11061                         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]);
11062                 }
11063         }
11064
11065         return t->currentframe;
11066 }
11067
11068 rsurfacestate_t rsurface;
11069
11070 void RSurf_ActiveWorldEntity(void)
11071 {
11072         dp_model_t *model = r_refdef.scene.worldmodel;
11073         //if (rsurface.entity == r_refdef.scene.worldentity)
11074         //      return;
11075         rsurface.entity = r_refdef.scene.worldentity;
11076         rsurface.skeleton = NULL;
11077         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
11078         rsurface.ent_skinnum = 0;
11079         rsurface.ent_qwskin = -1;
11080         rsurface.ent_shadertime = 0;
11081         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
11082         rsurface.matrix = identitymatrix;
11083         rsurface.inversematrix = identitymatrix;
11084         rsurface.matrixscale = 1;
11085         rsurface.inversematrixscale = 1;
11086         R_EntityMatrix(&identitymatrix);
11087         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
11088         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
11089         rsurface.fograngerecip = r_refdef.fograngerecip;
11090         rsurface.fogheightfade = r_refdef.fogheightfade;
11091         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
11092         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11093         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11094         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11095         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11096         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11097         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11098         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
11099         rsurface.colormod[3] = 1;
11100         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);
11101         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11102         rsurface.frameblend[0].lerp = 1;
11103         rsurface.ent_alttextures = false;
11104         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11105         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11106         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11107         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11108         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11109         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11110         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11111         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11112         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11113         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11114         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11115         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11116         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11117         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11118         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11119         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11120         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11121         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11122         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11123         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11124         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11125         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11126         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11127         rsurface.modelelement3i = model->surfmesh.data_element3i;
11128         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11129         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11130         rsurface.modelelement3s = model->surfmesh.data_element3s;
11131         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11132         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11133         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11134         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11135         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11136         rsurface.modelsurfaces = model->data_surfaces;
11137         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11138         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11139         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
11140         rsurface.modelgeneratedvertex = false;
11141         rsurface.batchgeneratedvertex = false;
11142         rsurface.batchfirstvertex = 0;
11143         rsurface.batchnumvertices = 0;
11144         rsurface.batchfirsttriangle = 0;
11145         rsurface.batchnumtriangles = 0;
11146         rsurface.batchvertex3f  = NULL;
11147         rsurface.batchvertex3f_vertexbuffer = NULL;
11148         rsurface.batchvertex3f_bufferoffset = 0;
11149         rsurface.batchsvector3f = NULL;
11150         rsurface.batchsvector3f_vertexbuffer = NULL;
11151         rsurface.batchsvector3f_bufferoffset = 0;
11152         rsurface.batchtvector3f = NULL;
11153         rsurface.batchtvector3f_vertexbuffer = NULL;
11154         rsurface.batchtvector3f_bufferoffset = 0;
11155         rsurface.batchnormal3f  = NULL;
11156         rsurface.batchnormal3f_vertexbuffer = NULL;
11157         rsurface.batchnormal3f_bufferoffset = 0;
11158         rsurface.batchlightmapcolor4f = NULL;
11159         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11160         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11161         rsurface.batchtexcoordtexture2f = NULL;
11162         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11163         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11164         rsurface.batchtexcoordlightmap2f = NULL;
11165         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11166         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11167         rsurface.batchvertexmesh = NULL;
11168         rsurface.batchvertexmeshbuffer = NULL;
11169         rsurface.batchvertex3fbuffer = NULL;
11170         rsurface.batchelement3i = NULL;
11171         rsurface.batchelement3i_indexbuffer = NULL;
11172         rsurface.batchelement3i_bufferoffset = 0;
11173         rsurface.batchelement3s = NULL;
11174         rsurface.batchelement3s_indexbuffer = NULL;
11175         rsurface.batchelement3s_bufferoffset = 0;
11176         rsurface.passcolor4f = NULL;
11177         rsurface.passcolor4f_vertexbuffer = NULL;
11178         rsurface.passcolor4f_bufferoffset = 0;
11179 }
11180
11181 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
11182 {
11183         dp_model_t *model = ent->model;
11184         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
11185         //      return;
11186         rsurface.entity = (entity_render_t *)ent;
11187         rsurface.skeleton = ent->skeleton;
11188         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
11189         rsurface.ent_skinnum = ent->skinnum;
11190         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;
11191         rsurface.ent_shadertime = ent->shadertime;
11192         rsurface.ent_flags = ent->flags;
11193         rsurface.matrix = ent->matrix;
11194         rsurface.inversematrix = ent->inversematrix;
11195         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11196         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11197         R_EntityMatrix(&rsurface.matrix);
11198         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11199         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11200         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11201         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11202         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11203         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11204         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
11205         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
11206         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
11207         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
11208         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
11209         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
11210         rsurface.colormod[3] = ent->alpha;
11211         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
11212         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
11213         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
11214         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11215         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11216         if (ent->model->brush.submodel && !prepass)
11217         {
11218                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
11219                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
11220         }
11221         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
11222         {
11223                 if (ent->animcache_vertex3f)
11224                 {
11225                         rsurface.modelvertex3f = ent->animcache_vertex3f;
11226                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
11227                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
11228                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
11229                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
11230                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
11231                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
11232                 }
11233                 else if (wanttangents)
11234                 {
11235                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11236                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11237                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11238                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11239                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
11240                         rsurface.modelvertexmesh = NULL;
11241                         rsurface.modelvertexmeshbuffer = NULL;
11242                         rsurface.modelvertex3fbuffer = NULL;
11243                 }
11244                 else if (wantnormals)
11245                 {
11246                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11247                         rsurface.modelsvector3f = NULL;
11248                         rsurface.modeltvector3f = NULL;
11249                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11250                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
11251                         rsurface.modelvertexmesh = NULL;
11252                         rsurface.modelvertexmeshbuffer = NULL;
11253                         rsurface.modelvertex3fbuffer = NULL;
11254                 }
11255                 else
11256                 {
11257                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11258                         rsurface.modelsvector3f = NULL;
11259                         rsurface.modeltvector3f = NULL;
11260                         rsurface.modelnormal3f = NULL;
11261                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
11262                         rsurface.modelvertexmesh = NULL;
11263                         rsurface.modelvertexmeshbuffer = NULL;
11264                         rsurface.modelvertex3fbuffer = NULL;
11265                 }
11266                 rsurface.modelvertex3f_vertexbuffer = 0;
11267                 rsurface.modelvertex3f_bufferoffset = 0;
11268                 rsurface.modelsvector3f_vertexbuffer = 0;
11269                 rsurface.modelsvector3f_bufferoffset = 0;
11270                 rsurface.modeltvector3f_vertexbuffer = 0;
11271                 rsurface.modeltvector3f_bufferoffset = 0;
11272                 rsurface.modelnormal3f_vertexbuffer = 0;
11273                 rsurface.modelnormal3f_bufferoffset = 0;
11274                 rsurface.modelgeneratedvertex = true;
11275         }
11276         else
11277         {
11278                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11279                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11280                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11281                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11282                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11283                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11284                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11285                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11286                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11287                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11288                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11289                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11290                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11291                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11292                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
11293                 rsurface.modelgeneratedvertex = false;
11294         }
11295         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11296         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11297         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11298         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11299         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11300         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11301         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11302         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11303         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11304         rsurface.modelelement3i = model->surfmesh.data_element3i;
11305         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11306         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11307         rsurface.modelelement3s = model->surfmesh.data_element3s;
11308         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11309         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11310         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11311         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11312         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11313         rsurface.modelsurfaces = model->data_surfaces;
11314         rsurface.batchgeneratedvertex = false;
11315         rsurface.batchfirstvertex = 0;
11316         rsurface.batchnumvertices = 0;
11317         rsurface.batchfirsttriangle = 0;
11318         rsurface.batchnumtriangles = 0;
11319         rsurface.batchvertex3f  = NULL;
11320         rsurface.batchvertex3f_vertexbuffer = NULL;
11321         rsurface.batchvertex3f_bufferoffset = 0;
11322         rsurface.batchsvector3f = NULL;
11323         rsurface.batchsvector3f_vertexbuffer = NULL;
11324         rsurface.batchsvector3f_bufferoffset = 0;
11325         rsurface.batchtvector3f = NULL;
11326         rsurface.batchtvector3f_vertexbuffer = NULL;
11327         rsurface.batchtvector3f_bufferoffset = 0;
11328         rsurface.batchnormal3f  = NULL;
11329         rsurface.batchnormal3f_vertexbuffer = NULL;
11330         rsurface.batchnormal3f_bufferoffset = 0;
11331         rsurface.batchlightmapcolor4f = NULL;
11332         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11333         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11334         rsurface.batchtexcoordtexture2f = NULL;
11335         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11336         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11337         rsurface.batchtexcoordlightmap2f = NULL;
11338         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11339         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11340         rsurface.batchvertexmesh = NULL;
11341         rsurface.batchvertexmeshbuffer = NULL;
11342         rsurface.batchvertex3fbuffer = NULL;
11343         rsurface.batchelement3i = NULL;
11344         rsurface.batchelement3i_indexbuffer = NULL;
11345         rsurface.batchelement3i_bufferoffset = 0;
11346         rsurface.batchelement3s = NULL;
11347         rsurface.batchelement3s_indexbuffer = NULL;
11348         rsurface.batchelement3s_bufferoffset = 0;
11349         rsurface.passcolor4f = NULL;
11350         rsurface.passcolor4f_vertexbuffer = NULL;
11351         rsurface.passcolor4f_bufferoffset = 0;
11352 }
11353
11354 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)
11355 {
11356         rsurface.entity = r_refdef.scene.worldentity;
11357         rsurface.skeleton = NULL;
11358         rsurface.ent_skinnum = 0;
11359         rsurface.ent_qwskin = -1;
11360         rsurface.ent_shadertime = shadertime;
11361         rsurface.ent_flags = entflags;
11362         rsurface.modelnumvertices = numvertices;
11363         rsurface.modelnumtriangles = numtriangles;
11364         rsurface.matrix = *matrix;
11365         rsurface.inversematrix = *inversematrix;
11366         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11367         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11368         R_EntityMatrix(&rsurface.matrix);
11369         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11370         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11371         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11372         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11373         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11374         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11375         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11376         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11377         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11378         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11379         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11380         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11381         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);
11382         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11383         rsurface.frameblend[0].lerp = 1;
11384         rsurface.ent_alttextures = false;
11385         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11386         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11387         if (wanttangents)
11388         {
11389                 rsurface.modelvertex3f = (float *)vertex3f;
11390                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11391                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11392                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11393         }
11394         else if (wantnormals)
11395         {
11396                 rsurface.modelvertex3f = (float *)vertex3f;
11397                 rsurface.modelsvector3f = NULL;
11398                 rsurface.modeltvector3f = NULL;
11399                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11400         }
11401         else
11402         {
11403                 rsurface.modelvertex3f = (float *)vertex3f;
11404                 rsurface.modelsvector3f = NULL;
11405                 rsurface.modeltvector3f = NULL;
11406                 rsurface.modelnormal3f = NULL;
11407         }
11408         rsurface.modelvertexmesh = NULL;
11409         rsurface.modelvertexmeshbuffer = NULL;
11410         rsurface.modelvertex3fbuffer = NULL;
11411         rsurface.modelvertex3f_vertexbuffer = 0;
11412         rsurface.modelvertex3f_bufferoffset = 0;
11413         rsurface.modelsvector3f_vertexbuffer = 0;
11414         rsurface.modelsvector3f_bufferoffset = 0;
11415         rsurface.modeltvector3f_vertexbuffer = 0;
11416         rsurface.modeltvector3f_bufferoffset = 0;
11417         rsurface.modelnormal3f_vertexbuffer = 0;
11418         rsurface.modelnormal3f_bufferoffset = 0;
11419         rsurface.modelgeneratedvertex = true;
11420         rsurface.modellightmapcolor4f  = (float *)color4f;
11421         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11422         rsurface.modellightmapcolor4f_bufferoffset = 0;
11423         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
11424         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11425         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11426         rsurface.modeltexcoordlightmap2f  = NULL;
11427         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11428         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11429         rsurface.modelelement3i = (int *)element3i;
11430         rsurface.modelelement3i_indexbuffer = NULL;
11431         rsurface.modelelement3i_bufferoffset = 0;
11432         rsurface.modelelement3s = (unsigned short *)element3s;
11433         rsurface.modelelement3s_indexbuffer = NULL;
11434         rsurface.modelelement3s_bufferoffset = 0;
11435         rsurface.modellightmapoffsets = NULL;
11436         rsurface.modelsurfaces = NULL;
11437         rsurface.batchgeneratedvertex = false;
11438         rsurface.batchfirstvertex = 0;
11439         rsurface.batchnumvertices = 0;
11440         rsurface.batchfirsttriangle = 0;
11441         rsurface.batchnumtriangles = 0;
11442         rsurface.batchvertex3f  = NULL;
11443         rsurface.batchvertex3f_vertexbuffer = NULL;
11444         rsurface.batchvertex3f_bufferoffset = 0;
11445         rsurface.batchsvector3f = NULL;
11446         rsurface.batchsvector3f_vertexbuffer = NULL;
11447         rsurface.batchsvector3f_bufferoffset = 0;
11448         rsurface.batchtvector3f = NULL;
11449         rsurface.batchtvector3f_vertexbuffer = NULL;
11450         rsurface.batchtvector3f_bufferoffset = 0;
11451         rsurface.batchnormal3f  = NULL;
11452         rsurface.batchnormal3f_vertexbuffer = NULL;
11453         rsurface.batchnormal3f_bufferoffset = 0;
11454         rsurface.batchlightmapcolor4f = NULL;
11455         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11456         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11457         rsurface.batchtexcoordtexture2f = NULL;
11458         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11459         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11460         rsurface.batchtexcoordlightmap2f = NULL;
11461         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11462         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11463         rsurface.batchvertexmesh = NULL;
11464         rsurface.batchvertexmeshbuffer = NULL;
11465         rsurface.batchvertex3fbuffer = NULL;
11466         rsurface.batchelement3i = NULL;
11467         rsurface.batchelement3i_indexbuffer = NULL;
11468         rsurface.batchelement3i_bufferoffset = 0;
11469         rsurface.batchelement3s = NULL;
11470         rsurface.batchelement3s_indexbuffer = NULL;
11471         rsurface.batchelement3s_bufferoffset = 0;
11472         rsurface.passcolor4f = NULL;
11473         rsurface.passcolor4f_vertexbuffer = NULL;
11474         rsurface.passcolor4f_bufferoffset = 0;
11475
11476         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11477         {
11478                 if ((wantnormals || wanttangents) && !normal3f)
11479                 {
11480                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11481                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11482                 }
11483                 if (wanttangents && !svector3f)
11484                 {
11485                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11486                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11487                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
11488                 }
11489         }
11490 }
11491
11492 float RSurf_FogPoint(const float *v)
11493 {
11494         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11495         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11496         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11497         float FogHeightFade = r_refdef.fogheightfade;
11498         float fogfrac;
11499         unsigned int fogmasktableindex;
11500         if (r_refdef.fogplaneviewabove)
11501                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11502         else
11503                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11504         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11505         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11506 }
11507
11508 float RSurf_FogVertex(const float *v)
11509 {
11510         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11511         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11512         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11513         float FogHeightFade = rsurface.fogheightfade;
11514         float fogfrac;
11515         unsigned int fogmasktableindex;
11516         if (r_refdef.fogplaneviewabove)
11517                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11518         else
11519                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11520         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11521         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11522 }
11523
11524 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11525 {
11526         int i;
11527         for (i = 0;i < numelements;i++)
11528                 outelement3i[i] = inelement3i[i] + adjust;
11529 }
11530
11531 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11532 extern cvar_t gl_vbo;
11533 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11534 {
11535         int deformindex;
11536         int firsttriangle;
11537         int numtriangles;
11538         int firstvertex;
11539         int endvertex;
11540         int numvertices;
11541         int surfacefirsttriangle;
11542         int surfacenumtriangles;
11543         int surfacefirstvertex;
11544         int surfaceendvertex;
11545         int surfacenumvertices;
11546         int batchnumvertices;
11547         int batchnumtriangles;
11548         int needsupdate;
11549         int i, j;
11550         qboolean gaps;
11551         qboolean dynamicvertex;
11552         float amplitude;
11553         float animpos;
11554         float scale;
11555         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11556         float waveparms[4];
11557         q3shaderinfo_deform_t *deform;
11558         const msurface_t *surface, *firstsurface;
11559         r_vertexmesh_t *vertexmesh;
11560         if (!texturenumsurfaces)
11561                 return;
11562         // find vertex range of this surface batch
11563         gaps = false;
11564         firstsurface = texturesurfacelist[0];
11565         firsttriangle = firstsurface->num_firsttriangle;
11566         batchnumvertices = 0;
11567         batchnumtriangles = 0;
11568         firstvertex = endvertex = firstsurface->num_firstvertex;
11569         for (i = 0;i < texturenumsurfaces;i++)
11570         {
11571                 surface = texturesurfacelist[i];
11572                 if (surface != firstsurface + i)
11573                         gaps = true;
11574                 surfacefirstvertex = surface->num_firstvertex;
11575                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11576                 surfacenumvertices = surface->num_vertices;
11577                 surfacenumtriangles = surface->num_triangles;
11578                 if (firstvertex > surfacefirstvertex)
11579                         firstvertex = surfacefirstvertex;
11580                 if (endvertex < surfaceendvertex)
11581                         endvertex = surfaceendvertex;
11582                 batchnumvertices += surfacenumvertices;
11583                 batchnumtriangles += surfacenumtriangles;
11584         }
11585
11586         // we now know the vertex range used, and if there are any gaps in it
11587         rsurface.batchfirstvertex = firstvertex;
11588         rsurface.batchnumvertices = endvertex - firstvertex;
11589         rsurface.batchfirsttriangle = firsttriangle;
11590         rsurface.batchnumtriangles = batchnumtriangles;
11591
11592         // this variable holds flags for which properties have been updated that
11593         // may require regenerating vertexmesh array...
11594         needsupdate = 0;
11595
11596         // check if any dynamic vertex processing must occur
11597         dynamicvertex = false;
11598
11599         // if there is a chance of animated vertex colors, it's a dynamic batch
11600         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11601         {
11602                 dynamicvertex = true;
11603                 batchneed |= BATCHNEED_NOGAPS;
11604                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
11605         }
11606
11607         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11608         {
11609                 switch (deform->deform)
11610                 {
11611                 default:
11612                 case Q3DEFORM_PROJECTIONSHADOW:
11613                 case Q3DEFORM_TEXT0:
11614                 case Q3DEFORM_TEXT1:
11615                 case Q3DEFORM_TEXT2:
11616                 case Q3DEFORM_TEXT3:
11617                 case Q3DEFORM_TEXT4:
11618                 case Q3DEFORM_TEXT5:
11619                 case Q3DEFORM_TEXT6:
11620                 case Q3DEFORM_TEXT7:
11621                 case Q3DEFORM_NONE:
11622                         break;
11623                 case Q3DEFORM_AUTOSPRITE:
11624                         dynamicvertex = true;
11625                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11626                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11627                         break;
11628                 case Q3DEFORM_AUTOSPRITE2:
11629                         dynamicvertex = true;
11630                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11631                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11632                         break;
11633                 case Q3DEFORM_NORMAL:
11634                         dynamicvertex = true;
11635                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11636                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11637                         break;
11638                 case Q3DEFORM_WAVE:
11639                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11640                                 break; // if wavefunc is a nop, ignore this transform
11641                         dynamicvertex = true;
11642                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11643                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11644                         break;
11645                 case Q3DEFORM_BULGE:
11646                         dynamicvertex = true;
11647                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11648                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11649                         break;
11650                 case Q3DEFORM_MOVE:
11651                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11652                                 break; // if wavefunc is a nop, ignore this transform
11653                         dynamicvertex = true;
11654                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11655                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
11656                         break;
11657                 }
11658         }
11659         switch(rsurface.texture->tcgen.tcgen)
11660         {
11661         default:
11662         case Q3TCGEN_TEXTURE:
11663                 break;
11664         case Q3TCGEN_LIGHTMAP:
11665                 dynamicvertex = true;
11666                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11667                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11668                 break;
11669         case Q3TCGEN_VECTOR:
11670                 dynamicvertex = true;
11671                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11672                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11673                 break;
11674         case Q3TCGEN_ENVIRONMENT:
11675                 dynamicvertex = true;
11676                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11677                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11678                 break;
11679         }
11680         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11681         {
11682                 dynamicvertex = true;
11683                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11684                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11685         }
11686
11687         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11688         {
11689                 dynamicvertex = true;
11690                 batchneed |= BATCHNEED_NOGAPS;
11691                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11692         }
11693
11694         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11695         {
11696                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11697                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11698                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11699                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11700                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11701                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11702                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11703         }
11704
11705         // when the model data has no vertex buffer (dynamic mesh), we need to
11706         // eliminate gaps
11707         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
11708                 batchneed |= BATCHNEED_NOGAPS;
11709
11710         // if needsupdate, we have to do a dynamic vertex batch for sure
11711         if (needsupdate & batchneed)
11712                 dynamicvertex = true;
11713
11714         // see if we need to build vertexmesh from arrays
11715         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11716                 dynamicvertex = true;
11717
11718         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11719         // also some drivers strongly dislike firstvertex
11720         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11721                 dynamicvertex = true;
11722
11723         rsurface.batchvertex3f = rsurface.modelvertex3f;
11724         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11725         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11726         rsurface.batchsvector3f = rsurface.modelsvector3f;
11727         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11728         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11729         rsurface.batchtvector3f = rsurface.modeltvector3f;
11730         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11731         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11732         rsurface.batchnormal3f = rsurface.modelnormal3f;
11733         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11734         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11735         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11736         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11737         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11738         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11739         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11740         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11741         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11742         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11743         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11744         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
11745         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11746         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11747         rsurface.batchelement3i = rsurface.modelelement3i;
11748         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11749         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11750         rsurface.batchelement3s = rsurface.modelelement3s;
11751         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11752         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11753
11754         // if any dynamic vertex processing has to occur in software, we copy the
11755         // entire surface list together before processing to rebase the vertices
11756         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11757         //
11758         // if any gaps exist and we do not have a static vertex buffer, we have to
11759         // copy the surface list together to avoid wasting upload bandwidth on the
11760         // vertices in the gaps.
11761         //
11762         // if gaps exist and we have a static vertex buffer, we still have to
11763         // combine the index buffer ranges into one dynamic index buffer.
11764         //
11765         // in all cases we end up with data that can be drawn in one call.
11766
11767         if (!dynamicvertex)
11768         {
11769                 // static vertex data, just set pointers...
11770                 rsurface.batchgeneratedvertex = false;
11771                 // if there are gaps, we want to build a combined index buffer,
11772                 // otherwise use the original static buffer with an appropriate offset
11773                 if (gaps)
11774                 {
11775                         // build a new triangle elements array for this batch
11776                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11777                         rsurface.batchfirsttriangle = 0;
11778                         numtriangles = 0;
11779                         for (i = 0;i < texturenumsurfaces;i++)
11780                         {
11781                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11782                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11783                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11784                                 numtriangles += surfacenumtriangles;
11785                         }
11786                         rsurface.batchelement3i_indexbuffer = NULL;
11787                         rsurface.batchelement3i_bufferoffset = 0;
11788                         rsurface.batchelement3s = NULL;
11789                         rsurface.batchelement3s_indexbuffer = NULL;
11790                         rsurface.batchelement3s_bufferoffset = 0;
11791                         if (endvertex <= 65536)
11792                         {
11793                                 // make a 16bit (unsigned short) index array if possible
11794                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11795                                 for (i = 0;i < numtriangles*3;i++)
11796                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11797                         }
11798                 }
11799                 return;
11800         }
11801
11802         // something needs software processing, do it for real...
11803         // we only directly handle separate array data in this case and then
11804         // generate interleaved data if needed...
11805         rsurface.batchgeneratedvertex = true;
11806
11807         // now copy the vertex data into a combined array and make an index array
11808         // (this is what Quake3 does all the time)
11809         //if (gaps || rsurface.batchfirstvertex)
11810         {
11811                 rsurface.batchvertex3fbuffer = NULL;
11812                 rsurface.batchvertexmesh = NULL;
11813                 rsurface.batchvertexmeshbuffer = NULL;
11814                 rsurface.batchvertex3f = NULL;
11815                 rsurface.batchvertex3f_vertexbuffer = NULL;
11816                 rsurface.batchvertex3f_bufferoffset = 0;
11817                 rsurface.batchsvector3f = NULL;
11818                 rsurface.batchsvector3f_vertexbuffer = NULL;
11819                 rsurface.batchsvector3f_bufferoffset = 0;
11820                 rsurface.batchtvector3f = NULL;
11821                 rsurface.batchtvector3f_vertexbuffer = NULL;
11822                 rsurface.batchtvector3f_bufferoffset = 0;
11823                 rsurface.batchnormal3f = NULL;
11824                 rsurface.batchnormal3f_vertexbuffer = NULL;
11825                 rsurface.batchnormal3f_bufferoffset = 0;
11826                 rsurface.batchlightmapcolor4f = NULL;
11827                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11828                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11829                 rsurface.batchtexcoordtexture2f = NULL;
11830                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11831                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11832                 rsurface.batchtexcoordlightmap2f = NULL;
11833                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11834                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11835                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11836                 rsurface.batchelement3i_indexbuffer = NULL;
11837                 rsurface.batchelement3i_bufferoffset = 0;
11838                 rsurface.batchelement3s = NULL;
11839                 rsurface.batchelement3s_indexbuffer = NULL;
11840                 rsurface.batchelement3s_bufferoffset = 0;
11841                 // we'll only be setting up certain arrays as needed
11842                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11843                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11844                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11845                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11846                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11847                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11848                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11849                 {
11850                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11851                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11852                 }
11853                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11854                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11855                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11856                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11857                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11858                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11859                 numvertices = 0;
11860                 numtriangles = 0;
11861                 for (i = 0;i < texturenumsurfaces;i++)
11862                 {
11863                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11864                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11865                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11866                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11867                         // copy only the data requested
11868                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11869                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11870                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11871                         {
11872                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11873                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11874                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11875                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11876                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11877                                 {
11878                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11879                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11880                                 }
11881                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11882                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11883                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11884                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11885                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11886                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11887                         }
11888                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11889                         numvertices += surfacenumvertices;
11890                         numtriangles += surfacenumtriangles;
11891                 }
11892
11893                 // generate a 16bit index array as well if possible
11894                 // (in general, dynamic batches fit)
11895                 if (numvertices <= 65536)
11896                 {
11897                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11898                         for (i = 0;i < numtriangles*3;i++)
11899                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11900                 }
11901
11902                 // since we've copied everything, the batch now starts at 0
11903                 rsurface.batchfirstvertex = 0;
11904                 rsurface.batchnumvertices = batchnumvertices;
11905                 rsurface.batchfirsttriangle = 0;
11906                 rsurface.batchnumtriangles = batchnumtriangles;
11907         }
11908
11909         // q1bsp surfaces rendered in vertex color mode have to have colors
11910         // calculated based on lightstyles
11911         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11912         {
11913                 // generate color arrays for the surfaces in this list
11914                 int c[4];
11915                 int scale;
11916                 int size3;
11917                 const int *offsets;
11918                 const unsigned char *lm;
11919                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11920                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11921                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11922                 numvertices = 0;
11923                 for (i = 0;i < texturenumsurfaces;i++)
11924                 {
11925                         surface = texturesurfacelist[i];
11926                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11927                         surfacenumvertices = surface->num_vertices;
11928                         if (surface->lightmapinfo->samples)
11929                         {
11930                                 for (j = 0;j < surfacenumvertices;j++)
11931                                 {
11932                                         lm = surface->lightmapinfo->samples + offsets[j];
11933                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11934                                         VectorScale(lm, scale, c);
11935                                         if (surface->lightmapinfo->styles[1] != 255)
11936                                         {
11937                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11938                                                 lm += size3;
11939                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11940                                                 VectorMA(c, scale, lm, c);
11941                                                 if (surface->lightmapinfo->styles[2] != 255)
11942                                                 {
11943                                                         lm += size3;
11944                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11945                                                         VectorMA(c, scale, lm, c);
11946                                                         if (surface->lightmapinfo->styles[3] != 255)
11947                                                         {
11948                                                                 lm += size3;
11949                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11950                                                                 VectorMA(c, scale, lm, c);
11951                                                         }
11952                                                 }
11953                                         }
11954                                         c[0] >>= 7;
11955                                         c[1] >>= 7;
11956                                         c[2] >>= 7;
11957                                         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);
11958                                         numvertices++;
11959                                 }
11960                         }
11961                         else
11962                         {
11963                                 for (j = 0;j < surfacenumvertices;j++)
11964                                 {
11965                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11966                                         numvertices++;
11967                                 }
11968                         }
11969                 }
11970         }
11971
11972         // if vertices are deformed (sprite flares and things in maps, possibly
11973         // water waves, bulges and other deformations), modify the copied vertices
11974         // in place
11975         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11976         {
11977                 switch (deform->deform)
11978                 {
11979                 default:
11980                 case Q3DEFORM_PROJECTIONSHADOW:
11981                 case Q3DEFORM_TEXT0:
11982                 case Q3DEFORM_TEXT1:
11983                 case Q3DEFORM_TEXT2:
11984                 case Q3DEFORM_TEXT3:
11985                 case Q3DEFORM_TEXT4:
11986                 case Q3DEFORM_TEXT5:
11987                 case Q3DEFORM_TEXT6:
11988                 case Q3DEFORM_TEXT7:
11989                 case Q3DEFORM_NONE:
11990                         break;
11991                 case Q3DEFORM_AUTOSPRITE:
11992                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11993                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11994                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11995                         VectorNormalize(newforward);
11996                         VectorNormalize(newright);
11997                         VectorNormalize(newup);
11998 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11999 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12000 //                      rsurface.batchvertex3f_bufferoffset = 0;
12001 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
12002 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
12003 //                      rsurface.batchsvector3f_bufferoffset = 0;
12004 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
12005 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
12006 //                      rsurface.batchtvector3f_bufferoffset = 0;
12007 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12008 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
12009 //                      rsurface.batchnormal3f_bufferoffset = 0;
12010                         // a single autosprite surface can contain multiple sprites...
12011                         for (j = 0;j < batchnumvertices - 3;j += 4)
12012                         {
12013                                 VectorClear(center);
12014                                 for (i = 0;i < 4;i++)
12015                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
12016                                 VectorScale(center, 0.25f, center);
12017                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
12018                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
12019                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
12020                                 for (i = 0;i < 4;i++)
12021                                 {
12022                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
12023                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
12024                                 }
12025                         }
12026                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
12027                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12028                         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);
12029                         break;
12030                 case Q3DEFORM_AUTOSPRITE2:
12031                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
12032                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
12033                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
12034                         VectorNormalize(newforward);
12035                         VectorNormalize(newright);
12036                         VectorNormalize(newup);
12037 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12038 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12039 //                      rsurface.batchvertex3f_bufferoffset = 0;
12040                         {
12041                                 const float *v1, *v2;
12042                                 vec3_t start, end;
12043                                 float f, l;
12044                                 struct
12045                                 {
12046                                         float length2;
12047                                         const float *v1;
12048                                         const float *v2;
12049                                 }
12050                                 shortest[2];
12051                                 memset(shortest, 0, sizeof(shortest));
12052                                 // a single autosprite surface can contain multiple sprites...
12053                                 for (j = 0;j < batchnumvertices - 3;j += 4)
12054                                 {
12055                                         VectorClear(center);
12056                                         for (i = 0;i < 4;i++)
12057                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
12058                                         VectorScale(center, 0.25f, center);
12059                                         // find the two shortest edges, then use them to define the
12060                                         // axis vectors for rotating around the central axis
12061                                         for (i = 0;i < 6;i++)
12062                                         {
12063                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
12064                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
12065                                                 l = VectorDistance2(v1, v2);
12066                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
12067                                                 if (v1[2] != v2[2])
12068                                                         l += (1.0f / 1024.0f);
12069                                                 if (shortest[0].length2 > l || i == 0)
12070                                                 {
12071                                                         shortest[1] = shortest[0];
12072                                                         shortest[0].length2 = l;
12073                                                         shortest[0].v1 = v1;
12074                                                         shortest[0].v2 = v2;
12075                                                 }
12076                                                 else if (shortest[1].length2 > l || i == 1)
12077                                                 {
12078                                                         shortest[1].length2 = l;
12079                                                         shortest[1].v1 = v1;
12080                                                         shortest[1].v2 = v2;
12081                                                 }
12082                                         }
12083                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
12084                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
12085                                         // this calculates the right vector from the shortest edge
12086                                         // and the up vector from the edge midpoints
12087                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
12088                                         VectorNormalize(right);
12089                                         VectorSubtract(end, start, up);
12090                                         VectorNormalize(up);
12091                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
12092                                         VectorSubtract(rsurface.localvieworigin, center, forward);
12093                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
12094                                         VectorNegate(forward, forward);
12095                                         VectorReflect(forward, 0, up, forward);
12096                                         VectorNormalize(forward);
12097                                         CrossProduct(up, forward, newright);
12098                                         VectorNormalize(newright);
12099                                         // rotate the quad around the up axis vector, this is made
12100                                         // especially easy by the fact we know the quad is flat,
12101                                         // so we only have to subtract the center position and
12102                                         // measure distance along the right vector, and then
12103                                         // multiply that by the newright vector and add back the
12104                                         // center position
12105                                         // we also need to subtract the old position to undo the
12106                                         // displacement from the center, which we do with a
12107                                         // DotProduct, the subtraction/addition of center is also
12108                                         // optimized into DotProducts here
12109                                         l = DotProduct(right, center);
12110                                         for (i = 0;i < 4;i++)
12111                                         {
12112                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
12113                                                 f = DotProduct(right, v1) - l;
12114                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
12115                                         }
12116                                 }
12117                         }
12118                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
12119                         {
12120 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12121 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
12122 //                              rsurface.batchnormal3f_bufferoffset = 0;
12123                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12124                         }
12125                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12126                         {
12127 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12128 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12129 //                              rsurface.batchsvector3f_bufferoffset = 0;
12130 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12131 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12132 //                              rsurface.batchtvector3f_bufferoffset = 0;
12133                                 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);
12134                         }
12135                         break;
12136                 case Q3DEFORM_NORMAL:
12137                         // deform the normals to make reflections wavey
12138                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12139                         rsurface.batchnormal3f_vertexbuffer = NULL;
12140                         rsurface.batchnormal3f_bufferoffset = 0;
12141                         for (j = 0;j < batchnumvertices;j++)
12142                         {
12143                                 float vertex[3];
12144                                 float *normal = rsurface.batchnormal3f + 3*j;
12145                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
12146                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
12147                                 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]);
12148                                 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]);
12149                                 VectorNormalize(normal);
12150                         }
12151                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12152                         {
12153 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12154 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12155 //                              rsurface.batchsvector3f_bufferoffset = 0;
12156 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12157 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12158 //                              rsurface.batchtvector3f_bufferoffset = 0;
12159                                 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);
12160                         }
12161                         break;
12162                 case Q3DEFORM_WAVE:
12163                         // deform vertex array to make wavey water and flags and such
12164                         waveparms[0] = deform->waveparms[0];
12165                         waveparms[1] = deform->waveparms[1];
12166                         waveparms[2] = deform->waveparms[2];
12167                         waveparms[3] = deform->waveparms[3];
12168                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
12169                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12170                         // this is how a divisor of vertex influence on deformation
12171                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
12172                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12173 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12174 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12175 //                      rsurface.batchvertex3f_bufferoffset = 0;
12176 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12177 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
12178 //                      rsurface.batchnormal3f_bufferoffset = 0;
12179                         for (j = 0;j < batchnumvertices;j++)
12180                         {
12181                                 // if the wavefunc depends on time, evaluate it per-vertex
12182                                 if (waveparms[3])
12183                                 {
12184                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
12185                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12186                                 }
12187                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
12188                         }
12189                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12190                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12191                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12192                         {
12193 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12194 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12195 //                              rsurface.batchsvector3f_bufferoffset = 0;
12196 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12197 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12198 //                              rsurface.batchtvector3f_bufferoffset = 0;
12199                                 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);
12200                         }
12201                         break;
12202                 case Q3DEFORM_BULGE:
12203                         // deform vertex array to make the surface have moving bulges
12204 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12205 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12206 //                      rsurface.batchvertex3f_bufferoffset = 0;
12207 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12208 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
12209 //                      rsurface.batchnormal3f_bufferoffset = 0;
12210                         for (j = 0;j < batchnumvertices;j++)
12211                         {
12212                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12213                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
12214                         }
12215                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12216                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12217                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12218                         {
12219 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12220 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12221 //                              rsurface.batchsvector3f_bufferoffset = 0;
12222 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12223 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12224 //                              rsurface.batchtvector3f_bufferoffset = 0;
12225                                 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);
12226                         }
12227                         break;
12228                 case Q3DEFORM_MOVE:
12229                         // deform vertex array
12230                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12231                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12232                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12233                         VectorScale(deform->parms, scale, waveparms);
12234 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12235 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12236 //                      rsurface.batchvertex3f_bufferoffset = 0;
12237                         for (j = 0;j < batchnumvertices;j++)
12238                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
12239                         break;
12240                 }
12241         }
12242
12243         // generate texcoords based on the chosen texcoord source
12244         switch(rsurface.texture->tcgen.tcgen)
12245         {
12246         default:
12247         case Q3TCGEN_TEXTURE:
12248                 break;
12249         case Q3TCGEN_LIGHTMAP:
12250 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12251 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12252 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12253                 if (rsurface.batchtexcoordlightmap2f)
12254                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
12255                 break;
12256         case Q3TCGEN_VECTOR:
12257 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12258 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12259 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12260                 for (j = 0;j < batchnumvertices;j++)
12261                 {
12262                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12263                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12264                 }
12265                 break;
12266         case Q3TCGEN_ENVIRONMENT:
12267                 // make environment reflections using a spheremap
12268                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12269                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12270                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12271                 for (j = 0;j < batchnumvertices;j++)
12272                 {
12273                         // identical to Q3A's method, but executed in worldspace so
12274                         // carried models can be shiny too
12275
12276                         float viewer[3], d, reflected[3], worldreflected[3];
12277
12278                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12279                         // VectorNormalize(viewer);
12280
12281                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12282
12283                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12284                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12285                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12286                         // note: this is proportinal to viewer, so we can normalize later
12287
12288                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12289                         VectorNormalize(worldreflected);
12290
12291                         // note: this sphere map only uses world x and z!
12292                         // so positive and negative y will LOOK THE SAME.
12293                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12294                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12295                 }
12296                 break;
12297         }
12298         // the only tcmod that needs software vertex processing is turbulent, so
12299         // check for it here and apply the changes if needed
12300         // and we only support that as the first one
12301         // (handling a mixture of turbulent and other tcmods would be problematic
12302         //  without punting it entirely to a software path)
12303         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12304         {
12305                 amplitude = rsurface.texture->tcmods[0].parms[1];
12306                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12307 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12308 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12309 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12310                 for (j = 0;j < batchnumvertices;j++)
12311                 {
12312                         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);
12313                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12314                 }
12315         }
12316
12317         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12318         {
12319                 // convert the modified arrays to vertex structs
12320 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
12321 //              rsurface.batchvertexmeshbuffer = NULL;
12322                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12323                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12324                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12325                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12326                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12327                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12328                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12329                 {
12330                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12331                         {
12332                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12333                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12334                         }
12335                 }
12336                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12337                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12338                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12339                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12340                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12341                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12342                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12343                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12344                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12345         }
12346 }
12347
12348 void RSurf_DrawBatch(void)
12349 {
12350         // sometimes a zero triangle surface (usually a degenerate patch) makes it
12351         // through the pipeline, killing it earlier in the pipeline would have
12352         // per-surface overhead rather than per-batch overhead, so it's best to
12353         // reject it here, before it hits glDraw.
12354         if (rsurface.batchnumtriangles == 0)
12355                 return;
12356 #if 0
12357         // batch debugging code
12358         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
12359         {
12360                 int i;
12361                 int j;
12362                 int c;
12363                 const int *e;
12364                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
12365                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
12366                 {
12367                         c = e[i];
12368                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
12369                         {
12370                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
12371                                 {
12372                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
12373                                                 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);
12374                                         break;
12375                                 }
12376                         }
12377                 }
12378         }
12379 #endif
12380         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);
12381 }
12382
12383 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12384 {
12385         // pick the closest matching water plane
12386         int planeindex, vertexindex, bestplaneindex = -1;
12387         float d, bestd;
12388         vec3_t vert;
12389         const float *v;
12390         r_waterstate_waterplane_t *p;
12391         qboolean prepared = false;
12392         bestd = 0;
12393         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12394         {
12395                 if(p->camera_entity != rsurface.texture->camera_entity)
12396                         continue;
12397                 d = 0;
12398                 if(!prepared)
12399                 {
12400                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12401                         prepared = true;
12402                         if(rsurface.batchnumvertices == 0)
12403                                 break;
12404                 }
12405                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12406                 {
12407                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12408                         d += fabs(PlaneDiff(vert, &p->plane));
12409                 }
12410                 if (bestd > d || bestplaneindex < 0)
12411                 {
12412                         bestd = d;
12413                         bestplaneindex = planeindex;
12414                 }
12415         }
12416         return bestplaneindex;
12417         // NOTE: this MAY return a totally unrelated water plane; we can ignore
12418         // this situation though, as it might be better to render single larger
12419         // batches with useless stuff (backface culled for example) than to
12420         // render multiple smaller batches
12421 }
12422
12423 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12424 {
12425         int i;
12426         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12427         rsurface.passcolor4f_vertexbuffer = 0;
12428         rsurface.passcolor4f_bufferoffset = 0;
12429         for (i = 0;i < rsurface.batchnumvertices;i++)
12430                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12431 }
12432
12433 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12434 {
12435         int i;
12436         float f;
12437         const float *v;
12438         const float *c;
12439         float *c2;
12440         if (rsurface.passcolor4f)
12441         {
12442                 // generate color arrays
12443                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
12444                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12445                 rsurface.passcolor4f_vertexbuffer = 0;
12446                 rsurface.passcolor4f_bufferoffset = 0;
12447                 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)
12448                 {
12449                         f = RSurf_FogVertex(v);
12450                         c2[0] = c[0] * f;
12451                         c2[1] = c[1] * f;
12452                         c2[2] = c[2] * f;
12453                         c2[3] = c[3];
12454                 }
12455         }
12456         else
12457         {
12458                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12459                 rsurface.passcolor4f_vertexbuffer = 0;
12460                 rsurface.passcolor4f_bufferoffset = 0;
12461                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12462                 {
12463                         f = RSurf_FogVertex(v);
12464                         c2[0] = f;
12465                         c2[1] = f;
12466                         c2[2] = f;
12467                         c2[3] = 1;
12468                 }
12469         }
12470 }
12471
12472 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12473 {
12474         int i;
12475         float f;
12476         const float *v;
12477         const float *c;
12478         float *c2;
12479         if (!rsurface.passcolor4f)
12480                 return;
12481         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
12482         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12483         rsurface.passcolor4f_vertexbuffer = 0;
12484         rsurface.passcolor4f_bufferoffset = 0;
12485         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)
12486         {
12487                 f = RSurf_FogVertex(v);
12488                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12489                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12490                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12491                 c2[3] = c[3];
12492         }
12493 }
12494
12495 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12496 {
12497         int i;
12498         const float *c;
12499         float *c2;
12500         if (!rsurface.passcolor4f)
12501                 return;
12502         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
12503         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12504         rsurface.passcolor4f_vertexbuffer = 0;
12505         rsurface.passcolor4f_bufferoffset = 0;
12506         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12507         {
12508                 c2[0] = c[0] * r;
12509                 c2[1] = c[1] * g;
12510                 c2[2] = c[2] * b;
12511                 c2[3] = c[3] * a;
12512         }
12513 }
12514
12515 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12516 {
12517         int i;
12518         const float *c;
12519         float *c2;
12520         if (!rsurface.passcolor4f)
12521                 return;
12522         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
12523         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12524         rsurface.passcolor4f_vertexbuffer = 0;
12525         rsurface.passcolor4f_bufferoffset = 0;
12526         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12527         {
12528                 c2[0] = c[0] + r_refdef.scene.ambient;
12529                 c2[1] = c[1] + r_refdef.scene.ambient;
12530                 c2[2] = c[2] + r_refdef.scene.ambient;
12531                 c2[3] = c[3];
12532         }
12533 }
12534
12535 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12536 {
12537         // TODO: optimize
12538         rsurface.passcolor4f = NULL;
12539         rsurface.passcolor4f_vertexbuffer = 0;
12540         rsurface.passcolor4f_bufferoffset = 0;
12541         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12542         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12543         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12544         GL_Color(r, g, b, a);
12545         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12546         RSurf_DrawBatch();
12547 }
12548
12549 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12550 {
12551         // TODO: optimize applyfog && applycolor case
12552         // just apply fog if necessary, and tint the fog color array if necessary
12553         rsurface.passcolor4f = NULL;
12554         rsurface.passcolor4f_vertexbuffer = 0;
12555         rsurface.passcolor4f_bufferoffset = 0;
12556         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12557         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12558         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12559         GL_Color(r, g, b, a);
12560         RSurf_DrawBatch();
12561 }
12562
12563 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12564 {
12565         // TODO: optimize
12566         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12567         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12568         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12569         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12570         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12571         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12572         GL_Color(r, g, b, a);
12573         RSurf_DrawBatch();
12574 }
12575
12576 static void RSurf_DrawBatch_GL11_ClampColor(void)
12577 {
12578         int i;
12579         const float *c1;
12580         float *c2;
12581         if (!rsurface.passcolor4f)
12582                 return;
12583         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12584         {
12585                 c2[0] = bound(0.0f, c1[0], 1.0f);
12586                 c2[1] = bound(0.0f, c1[1], 1.0f);
12587                 c2[2] = bound(0.0f, c1[2], 1.0f);
12588                 c2[3] = bound(0.0f, c1[3], 1.0f);
12589         }
12590 }
12591
12592 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12593 {
12594         int i;
12595         float f;
12596         const float *v;
12597         const float *n;
12598         float *c;
12599         //vec3_t eyedir;
12600
12601         // fake shading
12602         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12603         rsurface.passcolor4f_vertexbuffer = 0;
12604         rsurface.passcolor4f_bufferoffset = 0;
12605         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)
12606         {
12607                 f = -DotProduct(r_refdef.view.forward, n);
12608                 f = max(0, f);
12609                 f = f * 0.85 + 0.15; // work around so stuff won't get black
12610                 f *= r_refdef.lightmapintensity;
12611                 Vector4Set(c, f, f, f, 1);
12612         }
12613 }
12614
12615 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12616 {
12617         RSurf_DrawBatch_GL11_ApplyFakeLight();
12618         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12619         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12620         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12621         GL_Color(r, g, b, a);
12622         RSurf_DrawBatch();
12623 }
12624
12625 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12626 {
12627         int i;
12628         float f;
12629         float alpha;
12630         const float *v;
12631         const float *n;
12632         float *c;
12633         vec3_t ambientcolor;
12634         vec3_t diffusecolor;
12635         vec3_t lightdir;
12636         // TODO: optimize
12637         // model lighting
12638         VectorCopy(rsurface.modellight_lightdir, lightdir);
12639         f = 0.5f * r_refdef.lightmapintensity;
12640         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12641         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12642         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12643         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12644         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12645         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12646         alpha = *a;
12647         if (VectorLength2(diffusecolor) > 0)
12648         {
12649                 // q3-style directional shading
12650                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12651                 rsurface.passcolor4f_vertexbuffer = 0;
12652                 rsurface.passcolor4f_bufferoffset = 0;
12653                 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)
12654                 {
12655                         if ((f = DotProduct(n, lightdir)) > 0)
12656                                 VectorMA(ambientcolor, f, diffusecolor, c);
12657                         else
12658                                 VectorCopy(ambientcolor, c);
12659                         c[3] = alpha;
12660                 }
12661                 *r = 1;
12662                 *g = 1;
12663                 *b = 1;
12664                 *a = 1;
12665                 *applycolor = false;
12666         }
12667         else
12668         {
12669                 *r = ambientcolor[0];
12670                 *g = ambientcolor[1];
12671                 *b = ambientcolor[2];
12672                 rsurface.passcolor4f = NULL;
12673                 rsurface.passcolor4f_vertexbuffer = 0;
12674                 rsurface.passcolor4f_bufferoffset = 0;
12675         }
12676 }
12677
12678 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12679 {
12680         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12681         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12682         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12683         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12684         GL_Color(r, g, b, a);
12685         RSurf_DrawBatch();
12686 }
12687
12688 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12689 {
12690         int i;
12691         float f;
12692         const float *v;
12693         float *c;
12694         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12695         {
12696                 f = 1 - RSurf_FogVertex(v);
12697                 c[0] = r;
12698                 c[1] = g;
12699                 c[2] = b;
12700                 c[3] = f * a;
12701         }
12702 }
12703
12704 void RSurf_SetupDepthAndCulling(void)
12705 {
12706         // submodels are biased to avoid z-fighting with world surfaces that they
12707         // may be exactly overlapping (avoids z-fighting artifacts on certain
12708         // doors and things in Quake maps)
12709         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12710         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12711         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12712         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12713 }
12714
12715 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12716 {
12717         // transparent sky would be ridiculous
12718         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12719                 return;
12720         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12721         skyrenderlater = true;
12722         RSurf_SetupDepthAndCulling();
12723         GL_DepthMask(true);
12724         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12725         // skymasking on them, and Quake3 never did sky masking (unlike
12726         // software Quake and software Quake2), so disable the sky masking
12727         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12728         // and skymasking also looks very bad when noclipping outside the
12729         // level, so don't use it then either.
12730         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12731         {
12732                 R_Mesh_ResetTextureState();
12733                 if (skyrendermasked)
12734                 {
12735                         R_SetupShader_DepthOrShadow();
12736                         // depth-only (masking)
12737                         GL_ColorMask(0,0,0,0);
12738                         // just to make sure that braindead drivers don't draw
12739                         // anything despite that colormask...
12740                         GL_BlendFunc(GL_ZERO, GL_ONE);
12741                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12742                         if (rsurface.batchvertex3fbuffer)
12743                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12744                         else
12745                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12746                 }
12747                 else
12748                 {
12749                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12750                         // fog sky
12751                         GL_BlendFunc(GL_ONE, GL_ZERO);
12752                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12753                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12754                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12755                 }
12756                 RSurf_DrawBatch();
12757                 if (skyrendermasked)
12758                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12759         }
12760         R_Mesh_ResetTextureState();
12761         GL_Color(1, 1, 1, 1);
12762 }
12763
12764 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12765 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12766 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12767 {
12768         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12769                 return;
12770         if (prepass)
12771         {
12772                 // render screenspace normalmap to texture
12773                 GL_DepthMask(true);
12774                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12775                 RSurf_DrawBatch();
12776                 return;
12777         }
12778
12779         // bind lightmap texture
12780
12781         // water/refraction/reflection/camera surfaces have to be handled specially
12782         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12783         {
12784                 int start, end, startplaneindex;
12785                 for (start = 0;start < texturenumsurfaces;start = end)
12786                 {
12787                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12788                         if(startplaneindex < 0)
12789                         {
12790                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12791                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12792                                 end = start + 1;
12793                                 continue;
12794                         }
12795                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12796                                 ;
12797                         // now that we have a batch using the same planeindex, render it
12798                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12799                         {
12800                                 // render water or distortion background
12801                                 GL_DepthMask(true);
12802                                 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));
12803                                 RSurf_DrawBatch();
12804                                 // blend surface on top
12805                                 GL_DepthMask(false);
12806                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12807                                 RSurf_DrawBatch();
12808                         }
12809                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12810                         {
12811                                 // render surface with reflection texture as input
12812                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12813                                 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));
12814                                 RSurf_DrawBatch();
12815                         }
12816                 }
12817                 return;
12818         }
12819
12820         // render surface batch normally
12821         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12822         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12823         RSurf_DrawBatch();
12824 }
12825
12826 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12827 {
12828         // OpenGL 1.3 path - anything not completely ancient
12829         qboolean applycolor;
12830         qboolean applyfog;
12831         int layerindex;
12832         const texturelayer_t *layer;
12833         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);
12834         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12835
12836         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12837         {
12838                 vec4_t layercolor;
12839                 int layertexrgbscale;
12840                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12841                 {
12842                         if (layerindex == 0)
12843                                 GL_AlphaTest(true);
12844                         else
12845                         {
12846                                 GL_AlphaTest(false);
12847                                 GL_DepthFunc(GL_EQUAL);
12848                         }
12849                 }
12850                 GL_DepthMask(layer->depthmask && writedepth);
12851                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12852                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12853                 {
12854                         layertexrgbscale = 4;
12855                         VectorScale(layer->color, 0.25f, layercolor);
12856                 }
12857                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12858                 {
12859                         layertexrgbscale = 2;
12860                         VectorScale(layer->color, 0.5f, layercolor);
12861                 }
12862                 else
12863                 {
12864                         layertexrgbscale = 1;
12865                         VectorScale(layer->color, 1.0f, layercolor);
12866                 }
12867                 layercolor[3] = layer->color[3];
12868                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12869                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12870                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12871                 switch (layer->type)
12872                 {
12873                 case TEXTURELAYERTYPE_LITTEXTURE:
12874                         // single-pass lightmapped texture with 2x rgbscale
12875                         R_Mesh_TexBind(0, r_texture_white);
12876                         R_Mesh_TexMatrix(0, NULL);
12877                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12878                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12879                         R_Mesh_TexBind(1, layer->texture);
12880                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12881                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12882                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12883                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12884                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12885                         else if (FAKELIGHT_ENABLED)
12886                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12887                         else if (rsurface.uselightmaptexture)
12888                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12889                         else
12890                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12891                         break;
12892                 case TEXTURELAYERTYPE_TEXTURE:
12893                         // singletexture unlit texture with transparency support
12894                         R_Mesh_TexBind(0, layer->texture);
12895                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12896                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12897                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12898                         R_Mesh_TexBind(1, 0);
12899                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12900                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12901                         break;
12902                 case TEXTURELAYERTYPE_FOG:
12903                         // singletexture fogging
12904                         if (layer->texture)
12905                         {
12906                                 R_Mesh_TexBind(0, layer->texture);
12907                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12908                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12909                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12910                         }
12911                         else
12912                         {
12913                                 R_Mesh_TexBind(0, 0);
12914                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12915                         }
12916                         R_Mesh_TexBind(1, 0);
12917                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12918                         // generate a color array for the fog pass
12919                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12920                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12921                         RSurf_DrawBatch();
12922                         break;
12923                 default:
12924                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12925                 }
12926         }
12927         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12928         {
12929                 GL_DepthFunc(GL_LEQUAL);
12930                 GL_AlphaTest(false);
12931         }
12932 }
12933
12934 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12935 {
12936         // OpenGL 1.1 - crusty old voodoo path
12937         qboolean applyfog;
12938         int layerindex;
12939         const texturelayer_t *layer;
12940         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);
12941         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12942
12943         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12944         {
12945                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12946                 {
12947                         if (layerindex == 0)
12948                                 GL_AlphaTest(true);
12949                         else
12950                         {
12951                                 GL_AlphaTest(false);
12952                                 GL_DepthFunc(GL_EQUAL);
12953                         }
12954                 }
12955                 GL_DepthMask(layer->depthmask && writedepth);
12956                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12957                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12958                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12959                 switch (layer->type)
12960                 {
12961                 case TEXTURELAYERTYPE_LITTEXTURE:
12962                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12963                         {
12964                                 // two-pass lit texture with 2x rgbscale
12965                                 // first the lightmap pass
12966                                 R_Mesh_TexBind(0, r_texture_white);
12967                                 R_Mesh_TexMatrix(0, NULL);
12968                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12969                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12970                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12971                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12972                                 else if (FAKELIGHT_ENABLED)
12973                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12974                                 else if (rsurface.uselightmaptexture)
12975                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12976                                 else
12977                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12978                                 // then apply the texture to it
12979                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12980                                 R_Mesh_TexBind(0, layer->texture);
12981                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12982                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12983                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12984                                 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);
12985                         }
12986                         else
12987                         {
12988                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12989                                 R_Mesh_TexBind(0, layer->texture);
12990                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12991                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12992                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12993                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12994                                         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);
12995                                 else
12996                                         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);
12997                         }
12998                         break;
12999                 case TEXTURELAYERTYPE_TEXTURE:
13000                         // singletexture unlit texture with transparency support
13001                         R_Mesh_TexBind(0, layer->texture);
13002                         R_Mesh_TexMatrix(0, &layer->texmatrix);
13003                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
13004                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
13005                         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);
13006                         break;
13007                 case TEXTURELAYERTYPE_FOG:
13008                         // singletexture fogging
13009                         if (layer->texture)
13010                         {
13011                                 R_Mesh_TexBind(0, layer->texture);
13012                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
13013                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
13014                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
13015                         }
13016                         else
13017                         {
13018                                 R_Mesh_TexBind(0, 0);
13019                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
13020                         }
13021                         // generate a color array for the fog pass
13022                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
13023                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
13024                         RSurf_DrawBatch();
13025                         break;
13026                 default:
13027                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
13028                 }
13029         }
13030         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
13031         {
13032                 GL_DepthFunc(GL_LEQUAL);
13033                 GL_AlphaTest(false);
13034         }
13035 }
13036
13037 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
13038 {
13039         int vi;
13040         int j;
13041         r_vertexgeneric_t *batchvertex;
13042         float c[4];
13043
13044 //      R_Mesh_ResetTextureState();
13045         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13046
13047         if(rsurface.texture && rsurface.texture->currentskinframe)
13048         {
13049                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
13050                 c[3] *= rsurface.texture->currentalpha;
13051         }
13052         else
13053         {
13054                 c[0] = 1;
13055                 c[1] = 0;
13056                 c[2] = 1;
13057                 c[3] = 1;
13058         }
13059
13060         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
13061         {
13062                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
13063                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
13064                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
13065         }
13066
13067         // brighten it up (as texture value 127 means "unlit")
13068         c[0] *= 2 * r_refdef.view.colorscale;
13069         c[1] *= 2 * r_refdef.view.colorscale;
13070         c[2] *= 2 * r_refdef.view.colorscale;
13071
13072         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
13073                 c[3] *= r_wateralpha.value;
13074
13075         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
13076         {
13077                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13078                 GL_DepthMask(false);
13079         }
13080         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
13081         {
13082                 GL_BlendFunc(GL_ONE, GL_ONE);
13083                 GL_DepthMask(false);
13084         }
13085         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
13086         {
13087                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
13088                 GL_DepthMask(false);
13089         }
13090         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
13091         {
13092                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
13093                 GL_DepthMask(false);
13094         }
13095         else
13096         {
13097                 GL_BlendFunc(GL_ONE, GL_ZERO);
13098                 GL_DepthMask(writedepth);
13099         }
13100
13101         if (r_showsurfaces.integer == 3)
13102         {
13103                 rsurface.passcolor4f = NULL;
13104
13105                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
13106                 {
13107                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13108
13109                         rsurface.passcolor4f = NULL;
13110                         rsurface.passcolor4f_vertexbuffer = 0;
13111                         rsurface.passcolor4f_bufferoffset = 0;
13112                 }
13113                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
13114                 {
13115                         qboolean applycolor = true;
13116                         float one = 1.0;
13117
13118                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13119
13120                         r_refdef.lightmapintensity = 1;
13121                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
13122                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
13123                 }
13124                 else if (FAKELIGHT_ENABLED)
13125                 {
13126                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13127
13128                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
13129                         RSurf_DrawBatch_GL11_ApplyFakeLight();
13130                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
13131                 }
13132                 else
13133                 {
13134                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13135
13136                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
13137                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
13138                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
13139                 }
13140
13141                 if(!rsurface.passcolor4f)
13142                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
13143
13144                 RSurf_DrawBatch_GL11_ApplyAmbient();
13145                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
13146                 if(r_refdef.fogenabled)
13147                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
13148                 RSurf_DrawBatch_GL11_ClampColor();
13149
13150                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
13151                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13152                 RSurf_DrawBatch();
13153         }
13154         else if (!r_refdef.view.showdebug)
13155         {
13156                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13157                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13158                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13159                 {
13160                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13161                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
13162                 }
13163                 R_Mesh_PrepareVertices_Generic_Unlock();
13164                 RSurf_DrawBatch();
13165         }
13166         else if (r_showsurfaces.integer == 4)
13167         {
13168                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13169                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13170                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13171                 {
13172                         unsigned char c = vi << 3;
13173                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13174                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
13175                 }
13176                 R_Mesh_PrepareVertices_Generic_Unlock();
13177                 RSurf_DrawBatch();
13178         }
13179         else if (r_showsurfaces.integer == 2)
13180         {
13181                 const int *e;
13182                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13183                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
13184                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
13185                 {
13186                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
13187                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
13188                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
13189                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
13190                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
13191                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
13192                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
13193                 }
13194                 R_Mesh_PrepareVertices_Generic_Unlock();
13195                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
13196         }
13197         else
13198         {
13199                 int texturesurfaceindex;
13200                 int k;
13201                 const msurface_t *surface;
13202                 unsigned char surfacecolor4ub[4];
13203                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13204                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
13205                 vi = 0;
13206                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
13207                 {
13208                         surface = texturesurfacelist[texturesurfaceindex];
13209                         k = (int)(((size_t)surface) / sizeof(msurface_t));
13210                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
13211                         for (j = 0;j < surface->num_vertices;j++)
13212                         {
13213                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13214                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
13215                                 vi++;
13216                         }
13217                 }
13218                 R_Mesh_PrepareVertices_Generic_Unlock();
13219                 RSurf_DrawBatch();
13220         }
13221 }
13222
13223 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13224 {
13225         CHECKGLERROR
13226         RSurf_SetupDepthAndCulling();
13227         if (r_showsurfaces.integer)
13228         {
13229                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13230                 return;
13231         }
13232         switch (vid.renderpath)
13233         {
13234         case RENDERPATH_GL20:
13235         case RENDERPATH_CGGL:
13236         case RENDERPATH_D3D9:
13237         case RENDERPATH_D3D10:
13238         case RENDERPATH_D3D11:
13239         case RENDERPATH_SOFT:
13240         case RENDERPATH_GLES2:
13241                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13242                 break;
13243         case RENDERPATH_GL13:
13244                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13245                 break;
13246         case RENDERPATH_GL11:
13247                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13248                 break;
13249         }
13250         CHECKGLERROR
13251 }
13252
13253 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13254 {
13255         CHECKGLERROR
13256         RSurf_SetupDepthAndCulling();
13257         if (r_showsurfaces.integer)
13258         {
13259                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13260                 return;
13261         }
13262         switch (vid.renderpath)
13263         {
13264         case RENDERPATH_GL20:
13265         case RENDERPATH_CGGL:
13266         case RENDERPATH_D3D9:
13267         case RENDERPATH_D3D10:
13268         case RENDERPATH_D3D11:
13269         case RENDERPATH_SOFT:
13270         case RENDERPATH_GLES2:
13271                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13272                 break;
13273         case RENDERPATH_GL13:
13274                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13275                 break;
13276         case RENDERPATH_GL11:
13277                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13278                 break;
13279         }
13280         CHECKGLERROR
13281 }
13282
13283 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13284 {
13285         int i, j;
13286         int texturenumsurfaces, endsurface;
13287         texture_t *texture;
13288         const msurface_t *surface;
13289 #define MAXBATCH_TRANSPARENTSURFACES 256
13290         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13291
13292         // if the model is static it doesn't matter what value we give for
13293         // wantnormals and wanttangents, so this logic uses only rules applicable
13294         // to a model, knowing that they are meaningless otherwise
13295         if (ent == r_refdef.scene.worldentity)
13296                 RSurf_ActiveWorldEntity();
13297         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13298                 RSurf_ActiveModelEntity(ent, false, false, false);
13299         else
13300         {
13301                 switch (vid.renderpath)
13302                 {
13303                 case RENDERPATH_GL20:
13304                 case RENDERPATH_CGGL:
13305                 case RENDERPATH_D3D9:
13306                 case RENDERPATH_D3D10:
13307                 case RENDERPATH_D3D11:
13308                 case RENDERPATH_SOFT:
13309                 case RENDERPATH_GLES2:
13310                         RSurf_ActiveModelEntity(ent, true, true, false);
13311                         break;
13312                 case RENDERPATH_GL13:
13313                 case RENDERPATH_GL11:
13314                         RSurf_ActiveModelEntity(ent, true, false, false);
13315                         break;
13316                 }
13317         }
13318
13319         if (r_transparentdepthmasking.integer)
13320         {
13321                 qboolean setup = false;
13322                 for (i = 0;i < numsurfaces;i = j)
13323                 {
13324                         j = i + 1;
13325                         surface = rsurface.modelsurfaces + surfacelist[i];
13326                         texture = surface->texture;
13327                         rsurface.texture = R_GetCurrentTexture(texture);
13328                         rsurface.lightmaptexture = NULL;
13329                         rsurface.deluxemaptexture = NULL;
13330                         rsurface.uselightmaptexture = false;
13331                         // scan ahead until we find a different texture
13332                         endsurface = min(i + 1024, numsurfaces);
13333                         texturenumsurfaces = 0;
13334                         texturesurfacelist[texturenumsurfaces++] = surface;
13335                         for (;j < endsurface;j++)
13336                         {
13337                                 surface = rsurface.modelsurfaces + surfacelist[j];
13338                                 if (texture != surface->texture)
13339                                         break;
13340                                 texturesurfacelist[texturenumsurfaces++] = surface;
13341                         }
13342                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13343                                 continue;
13344                         // render the range of surfaces as depth
13345                         if (!setup)
13346                         {
13347                                 setup = true;
13348                                 GL_ColorMask(0,0,0,0);
13349                                 GL_Color(1,1,1,1);
13350                                 GL_DepthTest(true);
13351                                 GL_BlendFunc(GL_ONE, GL_ZERO);
13352                                 GL_DepthMask(true);
13353 //                              R_Mesh_ResetTextureState();
13354                                 R_SetupShader_DepthOrShadow();
13355                         }
13356                         RSurf_SetupDepthAndCulling();
13357                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
13358                         if (rsurface.batchvertex3fbuffer)
13359                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
13360                         else
13361                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
13362                         RSurf_DrawBatch();
13363                 }
13364                 if (setup)
13365                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13366         }
13367
13368         for (i = 0;i < numsurfaces;i = j)
13369         {
13370                 j = i + 1;
13371                 surface = rsurface.modelsurfaces + surfacelist[i];
13372                 texture = surface->texture;
13373                 rsurface.texture = R_GetCurrentTexture(texture);
13374                 // scan ahead until we find a different texture
13375                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13376                 texturenumsurfaces = 0;
13377                 texturesurfacelist[texturenumsurfaces++] = surface;
13378                 if(FAKELIGHT_ENABLED)
13379                 {
13380                         rsurface.lightmaptexture = NULL;
13381                         rsurface.deluxemaptexture = NULL;
13382                         rsurface.uselightmaptexture = false;
13383                         for (;j < endsurface;j++)
13384                         {
13385                                 surface = rsurface.modelsurfaces + surfacelist[j];
13386                                 if (texture != surface->texture)
13387                                         break;
13388                                 texturesurfacelist[texturenumsurfaces++] = surface;
13389                         }
13390                 }
13391                 else
13392                 {
13393                         rsurface.lightmaptexture = surface->lightmaptexture;
13394                         rsurface.deluxemaptexture = surface->deluxemaptexture;
13395                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13396                         for (;j < endsurface;j++)
13397                         {
13398                                 surface = rsurface.modelsurfaces + surfacelist[j];
13399                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13400                                         break;
13401                                 texturesurfacelist[texturenumsurfaces++] = surface;
13402                         }
13403                 }
13404                 // render the range of surfaces
13405                 if (ent == r_refdef.scene.worldentity)
13406                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13407                 else
13408                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13409         }
13410         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13411 }
13412
13413 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13414 {
13415         // transparent surfaces get pushed off into the transparent queue
13416         int surfacelistindex;
13417         const msurface_t *surface;
13418         vec3_t tempcenter, center;
13419         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13420         {
13421                 surface = texturesurfacelist[surfacelistindex];
13422                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13423                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13424                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13425                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13426                 if (queueentity->transparent_offset) // transparent offset
13427                 {
13428                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13429                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13430                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13431                 }
13432                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13433         }
13434 }
13435
13436 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13437 {
13438         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13439                 return;
13440         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13441                 return;
13442         RSurf_SetupDepthAndCulling();
13443         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
13444         if (rsurface.batchvertex3fbuffer)
13445                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
13446         else
13447                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
13448         RSurf_DrawBatch();
13449 }
13450
13451 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13452 {
13453         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13454         CHECKGLERROR
13455         if (depthonly)
13456                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13457         else if (prepass)
13458         {
13459                 if (!rsurface.texture->currentnumlayers)
13460                         return;
13461                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13462                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13463                 else
13464                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13465         }
13466         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13467                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13468         else if (!rsurface.texture->currentnumlayers)
13469                 return;
13470         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13471         {
13472                 // in the deferred case, transparent surfaces were queued during prepass
13473                 if (!r_shadow_usingdeferredprepass)
13474                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13475         }
13476         else
13477         {
13478                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13479                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13480         }
13481         CHECKGLERROR
13482 }
13483
13484 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13485 {
13486         int i, j;
13487         texture_t *texture;
13488         R_FrameData_SetMark();
13489         // break the surface list down into batches by texture and use of lightmapping
13490         for (i = 0;i < numsurfaces;i = j)
13491         {
13492                 j = i + 1;
13493                 // texture is the base texture pointer, rsurface.texture is the
13494                 // current frame/skin the texture is directing us to use (for example
13495                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13496                 // use skin 1 instead)
13497                 texture = surfacelist[i]->texture;
13498                 rsurface.texture = R_GetCurrentTexture(texture);
13499                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13500                 {
13501                         // if this texture is not the kind we want, skip ahead to the next one
13502                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13503                                 ;
13504                         continue;
13505                 }
13506                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13507                 {
13508                         rsurface.lightmaptexture = NULL;
13509                         rsurface.deluxemaptexture = NULL;
13510                         rsurface.uselightmaptexture = false;
13511                         // simply scan ahead until we find a different texture or lightmap state
13512                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13513                                 ;
13514                 }
13515                 else
13516                 {
13517                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13518                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13519                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13520                         // simply scan ahead until we find a different texture or lightmap state
13521                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13522                                 ;
13523                 }
13524                 // render the range of surfaces
13525                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13526         }
13527         R_FrameData_ReturnToMark();
13528 }
13529
13530 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13531 {
13532         CHECKGLERROR
13533         if (depthonly)
13534                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13535         else if (prepass)
13536         {
13537                 if (!rsurface.texture->currentnumlayers)
13538                         return;
13539                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13540                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13541                 else
13542                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13543         }
13544         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13545                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13546         else if (!rsurface.texture->currentnumlayers)
13547                 return;
13548         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13549         {
13550                 // in the deferred case, transparent surfaces were queued during prepass
13551                 if (!r_shadow_usingdeferredprepass)
13552                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13553         }
13554         else
13555         {
13556                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13557                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13558         }
13559         CHECKGLERROR
13560 }
13561
13562 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13563 {
13564         int i, j;
13565         texture_t *texture;
13566         R_FrameData_SetMark();
13567         // break the surface list down into batches by texture and use of lightmapping
13568         for (i = 0;i < numsurfaces;i = j)
13569         {
13570                 j = i + 1;
13571                 // texture is the base texture pointer, rsurface.texture is the
13572                 // current frame/skin the texture is directing us to use (for example
13573                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13574                 // use skin 1 instead)
13575                 texture = surfacelist[i]->texture;
13576                 rsurface.texture = R_GetCurrentTexture(texture);
13577                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13578                 {
13579                         // if this texture is not the kind we want, skip ahead to the next one
13580                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13581                                 ;
13582                         continue;
13583                 }
13584                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13585                 {
13586                         rsurface.lightmaptexture = NULL;
13587                         rsurface.deluxemaptexture = NULL;
13588                         rsurface.uselightmaptexture = false;
13589                         // simply scan ahead until we find a different texture or lightmap state
13590                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13591                                 ;
13592                 }
13593                 else
13594                 {
13595                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13596                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13597                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13598                         // simply scan ahead until we find a different texture or lightmap state
13599                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13600                                 ;
13601                 }
13602                 // render the range of surfaces
13603                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13604         }
13605         R_FrameData_ReturnToMark();
13606 }
13607
13608 float locboxvertex3f[6*4*3] =
13609 {
13610         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13611         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13612         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13613         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13614         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13615         1,0,0, 0,0,0, 0,1,0, 1,1,0
13616 };
13617
13618 unsigned short locboxelements[6*2*3] =
13619 {
13620          0, 1, 2, 0, 2, 3,
13621          4, 5, 6, 4, 6, 7,
13622          8, 9,10, 8,10,11,
13623         12,13,14, 12,14,15,
13624         16,17,18, 16,18,19,
13625         20,21,22, 20,22,23
13626 };
13627
13628 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13629 {
13630         int i, j;
13631         cl_locnode_t *loc = (cl_locnode_t *)ent;
13632         vec3_t mins, size;
13633         float vertex3f[6*4*3];
13634         CHECKGLERROR
13635         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13636         GL_DepthMask(false);
13637         GL_DepthRange(0, 1);
13638         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13639         GL_DepthTest(true);
13640         GL_CullFace(GL_NONE);
13641         R_EntityMatrix(&identitymatrix);
13642
13643 //      R_Mesh_ResetTextureState();
13644
13645         i = surfacelist[0];
13646         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13647                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13648                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13649                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13650
13651         if (VectorCompare(loc->mins, loc->maxs))
13652         {
13653                 VectorSet(size, 2, 2, 2);
13654                 VectorMA(loc->mins, -0.5f, size, mins);
13655         }
13656         else
13657         {
13658                 VectorCopy(loc->mins, mins);
13659                 VectorSubtract(loc->maxs, loc->mins, size);
13660         }
13661
13662         for (i = 0;i < 6*4*3;)
13663                 for (j = 0;j < 3;j++, i++)
13664                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13665
13666         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13667         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13668         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13669 }
13670
13671 void R_DrawLocs(void)
13672 {
13673         int index;
13674         cl_locnode_t *loc, *nearestloc;
13675         vec3_t center;
13676         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13677         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13678         {
13679                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13680                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13681         }
13682 }
13683
13684 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13685 {
13686         if (decalsystem->decals)
13687                 Mem_Free(decalsystem->decals);
13688         memset(decalsystem, 0, sizeof(*decalsystem));
13689 }
13690
13691 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)
13692 {
13693         tridecal_t *decal;
13694         tridecal_t *decals;
13695         int i;
13696
13697         // expand or initialize the system
13698         if (decalsystem->maxdecals <= decalsystem->numdecals)
13699         {
13700                 decalsystem_t old = *decalsystem;
13701                 qboolean useshortelements;
13702                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13703                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13704                 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)));
13705                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13706                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13707                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13708                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13709                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13710                 if (decalsystem->numdecals)
13711                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13712                 if (old.decals)
13713                         Mem_Free(old.decals);
13714                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13715                         decalsystem->element3i[i] = i;
13716                 if (useshortelements)
13717                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13718                                 decalsystem->element3s[i] = i;
13719         }
13720
13721         // grab a decal and search for another free slot for the next one
13722         decals = decalsystem->decals;
13723         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13724         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13725                 ;
13726         decalsystem->freedecal = i;
13727         if (decalsystem->numdecals <= i)
13728                 decalsystem->numdecals = i + 1;
13729
13730         // initialize the decal
13731         decal->lived = 0;
13732         decal->triangleindex = triangleindex;
13733         decal->surfaceindex = surfaceindex;
13734         decal->decalsequence = decalsequence;
13735         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13736         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13737         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13738         decal->color4ub[0][3] = 255;
13739         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13740         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13741         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13742         decal->color4ub[1][3] = 255;
13743         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13744         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13745         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13746         decal->color4ub[2][3] = 255;
13747         decal->vertex3f[0][0] = v0[0];
13748         decal->vertex3f[0][1] = v0[1];
13749         decal->vertex3f[0][2] = v0[2];
13750         decal->vertex3f[1][0] = v1[0];
13751         decal->vertex3f[1][1] = v1[1];
13752         decal->vertex3f[1][2] = v1[2];
13753         decal->vertex3f[2][0] = v2[0];
13754         decal->vertex3f[2][1] = v2[1];
13755         decal->vertex3f[2][2] = v2[2];
13756         decal->texcoord2f[0][0] = t0[0];
13757         decal->texcoord2f[0][1] = t0[1];
13758         decal->texcoord2f[1][0] = t1[0];
13759         decal->texcoord2f[1][1] = t1[1];
13760         decal->texcoord2f[2][0] = t2[0];
13761         decal->texcoord2f[2][1] = t2[1];
13762 }
13763
13764 extern cvar_t cl_decals_bias;
13765 extern cvar_t cl_decals_models;
13766 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13767 // baseparms, parms, temps
13768 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)
13769 {
13770         int cornerindex;
13771         int index;
13772         float v[9][3];
13773         const float *vertex3f;
13774         int numpoints;
13775         float points[2][9][3];
13776         float temp[3];
13777         float tc[9][2];
13778         float f;
13779         float c[9][4];
13780         const int *e;
13781
13782         e = rsurface.modelelement3i + 3*triangleindex;
13783
13784         vertex3f = rsurface.modelvertex3f;
13785
13786         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13787         {
13788                 index = 3*e[cornerindex];
13789                 VectorCopy(vertex3f + index, v[cornerindex]);
13790         }
13791         // cull backfaces
13792         //TriangleNormal(v[0], v[1], v[2], normal);
13793         //if (DotProduct(normal, localnormal) < 0.0f)
13794         //      continue;
13795         // clip by each of the box planes formed from the projection matrix
13796         // if anything survives, we emit the decal
13797         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]);
13798         if (numpoints < 3)
13799                 return;
13800         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]);
13801         if (numpoints < 3)
13802                 return;
13803         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]);
13804         if (numpoints < 3)
13805                 return;
13806         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]);
13807         if (numpoints < 3)
13808                 return;
13809         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]);
13810         if (numpoints < 3)
13811                 return;
13812         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]);
13813         if (numpoints < 3)
13814                 return;
13815         // some part of the triangle survived, so we have to accept it...
13816         if (dynamic)
13817         {
13818                 // dynamic always uses the original triangle
13819                 numpoints = 3;
13820                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13821                 {
13822                         index = 3*e[cornerindex];
13823                         VectorCopy(vertex3f + index, v[cornerindex]);
13824                 }
13825         }
13826         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13827         {
13828                 // convert vertex positions to texcoords
13829                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13830                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13831                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13832                 // calculate distance fade from the projection origin
13833                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13834                 f = bound(0.0f, f, 1.0f);
13835                 c[cornerindex][0] = r * f;
13836                 c[cornerindex][1] = g * f;
13837                 c[cornerindex][2] = b * f;
13838                 c[cornerindex][3] = 1.0f;
13839                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13840         }
13841         if (dynamic)
13842                 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);
13843         else
13844                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13845                         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);
13846 }
13847 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)
13848 {
13849         matrix4x4_t projection;
13850         decalsystem_t *decalsystem;
13851         qboolean dynamic;
13852         dp_model_t *model;
13853         const msurface_t *surface;
13854         const msurface_t *surfaces;
13855         const int *surfacelist;
13856         const texture_t *texture;
13857         int numtriangles;
13858         int numsurfacelist;
13859         int surfacelistindex;
13860         int surfaceindex;
13861         int triangleindex;
13862         float localorigin[3];
13863         float localnormal[3];
13864         float localmins[3];
13865         float localmaxs[3];
13866         float localsize;
13867         //float normal[3];
13868         float planes[6][4];
13869         float angles[3];
13870         bih_t *bih;
13871         int bih_triangles_count;
13872         int bih_triangles[256];
13873         int bih_surfaces[256];
13874
13875         decalsystem = &ent->decalsystem;
13876         model = ent->model;
13877         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13878         {
13879                 R_DecalSystem_Reset(&ent->decalsystem);
13880                 return;
13881         }
13882
13883         if (!model->brush.data_leafs && !cl_decals_models.integer)
13884         {
13885                 if (decalsystem->model)
13886                         R_DecalSystem_Reset(decalsystem);
13887                 return;
13888         }
13889
13890         if (decalsystem->model != model)
13891                 R_DecalSystem_Reset(decalsystem);
13892         decalsystem->model = model;
13893
13894         RSurf_ActiveModelEntity(ent, false, false, false);
13895
13896         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13897         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13898         VectorNormalize(localnormal);
13899         localsize = worldsize*rsurface.inversematrixscale;
13900         localmins[0] = localorigin[0] - localsize;
13901         localmins[1] = localorigin[1] - localsize;
13902         localmins[2] = localorigin[2] - localsize;
13903         localmaxs[0] = localorigin[0] + localsize;
13904         localmaxs[1] = localorigin[1] + localsize;
13905         localmaxs[2] = localorigin[2] + localsize;
13906
13907         //VectorCopy(localnormal, planes[4]);
13908         //VectorVectors(planes[4], planes[2], planes[0]);
13909         AnglesFromVectors(angles, localnormal, NULL, false);
13910         AngleVectors(angles, planes[0], planes[2], planes[4]);
13911         VectorNegate(planes[0], planes[1]);
13912         VectorNegate(planes[2], planes[3]);
13913         VectorNegate(planes[4], planes[5]);
13914         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13915         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13916         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13917         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13918         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13919         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13920
13921 #if 1
13922 // works
13923 {
13924         matrix4x4_t forwardprojection;
13925         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13926         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13927 }
13928 #else
13929 // broken
13930 {
13931         float projectionvector[4][3];
13932         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13933         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13934         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13935         projectionvector[0][0] = planes[0][0] * ilocalsize;
13936         projectionvector[0][1] = planes[1][0] * ilocalsize;
13937         projectionvector[0][2] = planes[2][0] * ilocalsize;
13938         projectionvector[1][0] = planes[0][1] * ilocalsize;
13939         projectionvector[1][1] = planes[1][1] * ilocalsize;
13940         projectionvector[1][2] = planes[2][1] * ilocalsize;
13941         projectionvector[2][0] = planes[0][2] * ilocalsize;
13942         projectionvector[2][1] = planes[1][2] * ilocalsize;
13943         projectionvector[2][2] = planes[2][2] * ilocalsize;
13944         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13945         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13946         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13947         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13948 }
13949 #endif
13950
13951         dynamic = model->surfmesh.isanimated;
13952         numsurfacelist = model->nummodelsurfaces;
13953         surfacelist = model->sortedmodelsurfaces;
13954         surfaces = model->data_surfaces;
13955
13956         bih = NULL;
13957         bih_triangles_count = -1;
13958         if(!dynamic)
13959         {
13960                 if(model->render_bih.numleafs)
13961                         bih = &model->render_bih;
13962                 else if(model->collision_bih.numleafs)
13963                         bih = &model->collision_bih;
13964         }
13965         if(bih)
13966                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13967         if(bih_triangles_count == 0)
13968                 return;
13969         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13970                 return;
13971         if(bih_triangles_count > 0)
13972         {
13973                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13974                 {
13975                         surfaceindex = bih_surfaces[triangleindex];
13976                         surface = surfaces + surfaceindex;
13977                         texture = surface->texture;
13978                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13979                                 continue;
13980                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13981                                 continue;
13982                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13983                 }
13984         }
13985         else
13986         {
13987                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13988                 {
13989                         surfaceindex = surfacelist[surfacelistindex];
13990                         surface = surfaces + surfaceindex;
13991                         // check cull box first because it rejects more than any other check
13992                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13993                                 continue;
13994                         // skip transparent surfaces
13995                         texture = surface->texture;
13996                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13997                                 continue;
13998                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13999                                 continue;
14000                         numtriangles = surface->num_triangles;
14001                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
14002                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
14003                 }
14004         }
14005 }
14006
14007 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
14008 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)
14009 {
14010         int renderentityindex;
14011         float worldmins[3];
14012         float worldmaxs[3];
14013         entity_render_t *ent;
14014
14015         if (!cl_decals_newsystem.integer)
14016                 return;
14017
14018         worldmins[0] = worldorigin[0] - worldsize;
14019         worldmins[1] = worldorigin[1] - worldsize;
14020         worldmins[2] = worldorigin[2] - worldsize;
14021         worldmaxs[0] = worldorigin[0] + worldsize;
14022         worldmaxs[1] = worldorigin[1] + worldsize;
14023         worldmaxs[2] = worldorigin[2] + worldsize;
14024
14025         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
14026
14027         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
14028         {
14029                 ent = r_refdef.scene.entities[renderentityindex];
14030                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
14031                         continue;
14032
14033                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
14034         }
14035 }
14036
14037 typedef struct r_decalsystem_splatqueue_s
14038 {
14039         vec3_t worldorigin;
14040         vec3_t worldnormal;
14041         float color[4];
14042         float tcrange[4];
14043         float worldsize;
14044         int decalsequence;
14045 }
14046 r_decalsystem_splatqueue_t;
14047
14048 int r_decalsystem_numqueued = 0;
14049 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
14050
14051 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)
14052 {
14053         r_decalsystem_splatqueue_t *queue;
14054
14055         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
14056                 return;
14057
14058         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
14059         VectorCopy(worldorigin, queue->worldorigin);
14060         VectorCopy(worldnormal, queue->worldnormal);
14061         Vector4Set(queue->color, r, g, b, a);
14062         Vector4Set(queue->tcrange, s1, t1, s2, t2);
14063         queue->worldsize = worldsize;
14064         queue->decalsequence = cl.decalsequence++;
14065 }
14066
14067 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
14068 {
14069         int i;
14070         r_decalsystem_splatqueue_t *queue;
14071
14072         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
14073                 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);
14074         r_decalsystem_numqueued = 0;
14075 }
14076
14077 extern cvar_t cl_decals_max;
14078 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
14079 {
14080         int i;
14081         decalsystem_t *decalsystem = &ent->decalsystem;
14082         int numdecals;
14083         int killsequence;
14084         tridecal_t *decal;
14085         float frametime;
14086         float lifetime;
14087
14088         if (!decalsystem->numdecals)
14089                 return;
14090
14091         if (r_showsurfaces.integer)
14092                 return;
14093
14094         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
14095         {
14096                 R_DecalSystem_Reset(decalsystem);
14097                 return;
14098         }
14099
14100         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
14101         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
14102
14103         if (decalsystem->lastupdatetime)
14104                 frametime = (cl.time - decalsystem->lastupdatetime);
14105         else
14106                 frametime = 0;
14107         decalsystem->lastupdatetime = cl.time;
14108         decal = decalsystem->decals;
14109         numdecals = decalsystem->numdecals;
14110
14111         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14112         {
14113                 if (decal->color4ub[0][3])
14114                 {
14115                         decal->lived += frametime;
14116                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
14117                         {
14118                                 memset(decal, 0, sizeof(*decal));
14119                                 if (decalsystem->freedecal > i)
14120                                         decalsystem->freedecal = i;
14121                         }
14122                 }
14123         }
14124         decal = decalsystem->decals;
14125         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
14126                 numdecals--;
14127
14128         // collapse the array by shuffling the tail decals into the gaps
14129         for (;;)
14130         {
14131                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
14132                         decalsystem->freedecal++;
14133                 if (decalsystem->freedecal == numdecals)
14134                         break;
14135                 decal[decalsystem->freedecal] = decal[--numdecals];
14136         }
14137
14138         decalsystem->numdecals = numdecals;
14139
14140         if (numdecals <= 0)
14141         {
14142                 // if there are no decals left, reset decalsystem
14143                 R_DecalSystem_Reset(decalsystem);
14144         }
14145 }
14146
14147 extern skinframe_t *decalskinframe;
14148 static void R_DrawModelDecals_Entity(entity_render_t *ent)
14149 {
14150         int i;
14151         decalsystem_t *decalsystem = &ent->decalsystem;
14152         int numdecals;
14153         tridecal_t *decal;
14154         float faderate;
14155         float alpha;
14156         float *v3f;
14157         float *c4f;
14158         float *t2f;
14159         const int *e;
14160         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
14161         int numtris = 0;
14162
14163         numdecals = decalsystem->numdecals;
14164         if (!numdecals)
14165                 return;
14166
14167         if (r_showsurfaces.integer)
14168                 return;
14169
14170         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
14171         {
14172                 R_DecalSystem_Reset(decalsystem);
14173                 return;
14174         }
14175
14176         // if the model is static it doesn't matter what value we give for
14177         // wantnormals and wanttangents, so this logic uses only rules applicable
14178         // to a model, knowing that they are meaningless otherwise
14179         if (ent == r_refdef.scene.worldentity)
14180                 RSurf_ActiveWorldEntity();
14181         else
14182                 RSurf_ActiveModelEntity(ent, false, false, false);
14183
14184         decalsystem->lastupdatetime = cl.time;
14185         decal = decalsystem->decals;
14186
14187         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
14188
14189         // update vertex positions for animated models
14190         v3f = decalsystem->vertex3f;
14191         c4f = decalsystem->color4f;
14192         t2f = decalsystem->texcoord2f;
14193         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14194         {
14195                 if (!decal->color4ub[0][3])
14196                         continue;
14197
14198                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
14199                         continue;
14200
14201                 // update color values for fading decals
14202                 if (decal->lived >= cl_decals_time.value)
14203                 {
14204                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
14205                         alpha *= (1.0f/255.0f);
14206                 }
14207                 else
14208                         alpha = 1.0f/255.0f;
14209
14210                 c4f[ 0] = decal->color4ub[0][0] * alpha;
14211                 c4f[ 1] = decal->color4ub[0][1] * alpha;
14212                 c4f[ 2] = decal->color4ub[0][2] * alpha;
14213                 c4f[ 3] = 1;
14214                 c4f[ 4] = decal->color4ub[1][0] * alpha;
14215                 c4f[ 5] = decal->color4ub[1][1] * alpha;
14216                 c4f[ 6] = decal->color4ub[1][2] * alpha;
14217                 c4f[ 7] = 1;
14218                 c4f[ 8] = decal->color4ub[2][0] * alpha;
14219                 c4f[ 9] = decal->color4ub[2][1] * alpha;
14220                 c4f[10] = decal->color4ub[2][2] * alpha;
14221                 c4f[11] = 1;
14222
14223                 t2f[0] = decal->texcoord2f[0][0];
14224                 t2f[1] = decal->texcoord2f[0][1];
14225                 t2f[2] = decal->texcoord2f[1][0];
14226                 t2f[3] = decal->texcoord2f[1][1];
14227                 t2f[4] = decal->texcoord2f[2][0];
14228                 t2f[5] = decal->texcoord2f[2][1];
14229
14230                 // update vertex positions for animated models
14231                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
14232                 {
14233                         e = rsurface.modelelement3i + 3*decal->triangleindex;
14234                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
14235                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
14236                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
14237                 }
14238                 else
14239                 {
14240                         VectorCopy(decal->vertex3f[0], v3f);
14241                         VectorCopy(decal->vertex3f[1], v3f + 3);
14242                         VectorCopy(decal->vertex3f[2], v3f + 6);
14243                 }
14244
14245                 if (r_refdef.fogenabled)
14246                 {
14247                         alpha = RSurf_FogVertex(v3f);
14248                         VectorScale(c4f, alpha, c4f);
14249                         alpha = RSurf_FogVertex(v3f + 3);
14250                         VectorScale(c4f + 4, alpha, c4f + 4);
14251                         alpha = RSurf_FogVertex(v3f + 6);
14252                         VectorScale(c4f + 8, alpha, c4f + 8);
14253                 }
14254
14255                 v3f += 9;
14256                 c4f += 12;
14257                 t2f += 6;
14258                 numtris++;
14259         }
14260
14261         if (numtris > 0)
14262         {
14263                 r_refdef.stats.drawndecals += numtris;
14264
14265                 // now render the decals all at once
14266                 // (this assumes they all use one particle font texture!)
14267                 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);
14268 //              R_Mesh_ResetTextureState();
14269                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14270                 GL_DepthMask(false);
14271                 GL_DepthRange(0, 1);
14272                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14273                 GL_DepthTest(true);
14274                 GL_CullFace(GL_NONE);
14275                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14276                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14277                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14278         }
14279 }
14280
14281 static void R_DrawModelDecals(void)
14282 {
14283         int i, numdecals;
14284
14285         // fade faster when there are too many decals
14286         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14287         for (i = 0;i < r_refdef.scene.numentities;i++)
14288                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14289
14290         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14291         for (i = 0;i < r_refdef.scene.numentities;i++)
14292                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14293                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14294
14295         R_DecalSystem_ApplySplatEntitiesQueue();
14296
14297         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14298         for (i = 0;i < r_refdef.scene.numentities;i++)
14299                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14300
14301         r_refdef.stats.totaldecals += numdecals;
14302
14303         if (r_showsurfaces.integer)
14304                 return;
14305
14306         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14307
14308         for (i = 0;i < r_refdef.scene.numentities;i++)
14309         {
14310                 if (!r_refdef.viewcache.entityvisible[i])
14311                         continue;
14312                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14313                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14314         }
14315 }
14316
14317 extern cvar_t mod_collision_bih;
14318 void R_DrawDebugModel(void)
14319 {
14320         entity_render_t *ent = rsurface.entity;
14321         int i, j, k, l, flagsmask;
14322         const msurface_t *surface;
14323         dp_model_t *model = ent->model;
14324         vec3_t v;
14325
14326         switch(vid.renderpath)
14327         {
14328         case RENDERPATH_GL11:
14329         case RENDERPATH_GL13:
14330         case RENDERPATH_GL20:
14331         case RENDERPATH_CGGL:
14332                 break;
14333         case RENDERPATH_D3D9:
14334                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14335                 return;
14336         case RENDERPATH_D3D10:
14337                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14338                 return;
14339         case RENDERPATH_D3D11:
14340                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14341                 return;
14342         case RENDERPATH_SOFT:
14343                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14344                 return;
14345         case RENDERPATH_GLES2:
14346                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14347                 return;
14348         }
14349
14350         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14351
14352 //      R_Mesh_ResetTextureState();
14353         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14354         GL_DepthRange(0, 1);
14355         GL_DepthTest(!r_showdisabledepthtest.integer);
14356         GL_DepthMask(false);
14357         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14358
14359         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14360         {
14361                 int triangleindex;
14362                 int bihleafindex;
14363                 qboolean cullbox = ent == r_refdef.scene.worldentity;
14364                 const q3mbrush_t *brush;
14365                 const bih_t *bih = &model->collision_bih;
14366                 const bih_leaf_t *bihleaf;
14367                 float vertex3f[3][3];
14368                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14369                 cullbox = false;
14370                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14371                 {
14372                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14373                                 continue;
14374                         switch (bihleaf->type)
14375                         {
14376                         case BIH_BRUSH:
14377                                 brush = model->brush.data_brushes + bihleaf->itemindex;
14378                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
14379                                 {
14380                                         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);
14381                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14382                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14383                                 }
14384                                 break;
14385                         case BIH_COLLISIONTRIANGLE:
14386                                 triangleindex = bihleaf->itemindex;
14387                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14388                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14389                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14390                                 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);
14391                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14392                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14393                                 break;
14394                         case BIH_RENDERTRIANGLE:
14395                                 triangleindex = bihleaf->itemindex;
14396                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14397                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14398                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14399                                 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);
14400                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14401                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14402                                 break;
14403                         }
14404                 }
14405         }
14406
14407         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14408
14409         if (r_showtris.integer || (r_shownormals.value != 0))
14410         {
14411                 if (r_showdisabledepthtest.integer)
14412                 {
14413                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14414                         GL_DepthMask(false);
14415                 }
14416                 else
14417                 {
14418                         GL_BlendFunc(GL_ONE, GL_ZERO);
14419                         GL_DepthMask(true);
14420                 }
14421                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14422                 {
14423                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14424                                 continue;
14425                         rsurface.texture = R_GetCurrentTexture(surface->texture);
14426                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14427                         {
14428                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14429                                 if (r_showtris.value > 0)
14430                                 {
14431                                         if (!rsurface.texture->currentlayers->depthmask)
14432                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14433                                         else if (ent == r_refdef.scene.worldentity)
14434                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14435                                         else
14436                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14437                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14438                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14439                                         RSurf_DrawBatch();
14440                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14441                                         CHECKGLERROR
14442                                 }
14443                                 if (r_shownormals.value < 0)
14444                                 {
14445                                         qglBegin(GL_LINES);
14446                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14447                                         {
14448                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14449                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14450                                                 qglVertex3f(v[0], v[1], v[2]);
14451                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14452                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14453                                                 qglVertex3f(v[0], v[1], v[2]);
14454                                         }
14455                                         qglEnd();
14456                                         CHECKGLERROR
14457                                 }
14458                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14459                                 {
14460                                         qglBegin(GL_LINES);
14461                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14462                                         {
14463                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14464                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14465                                                 qglVertex3f(v[0], v[1], v[2]);
14466                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14467                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14468                                                 qglVertex3f(v[0], v[1], v[2]);
14469                                         }
14470                                         qglEnd();
14471                                         CHECKGLERROR
14472                                         qglBegin(GL_LINES);
14473                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14474                                         {
14475                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14476                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14477                                                 qglVertex3f(v[0], v[1], v[2]);
14478                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14479                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14480                                                 qglVertex3f(v[0], v[1], v[2]);
14481                                         }
14482                                         qglEnd();
14483                                         CHECKGLERROR
14484                                         qglBegin(GL_LINES);
14485                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14486                                         {
14487                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14488                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14489                                                 qglVertex3f(v[0], v[1], v[2]);
14490                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14491                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14492                                                 qglVertex3f(v[0], v[1], v[2]);
14493                                         }
14494                                         qglEnd();
14495                                         CHECKGLERROR
14496                                 }
14497                         }
14498                 }
14499                 rsurface.texture = NULL;
14500         }
14501 }
14502
14503 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14504 int r_maxsurfacelist = 0;
14505 const msurface_t **r_surfacelist = NULL;
14506 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14507 {
14508         int i, j, endj, flagsmask;
14509         dp_model_t *model = r_refdef.scene.worldmodel;
14510         msurface_t *surfaces;
14511         unsigned char *update;
14512         int numsurfacelist = 0;
14513         if (model == NULL)
14514                 return;
14515
14516         if (r_maxsurfacelist < model->num_surfaces)
14517         {
14518                 r_maxsurfacelist = model->num_surfaces;
14519                 if (r_surfacelist)
14520                         Mem_Free((msurface_t**)r_surfacelist);
14521                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14522         }
14523
14524         RSurf_ActiveWorldEntity();
14525
14526         surfaces = model->data_surfaces;
14527         update = model->brushq1.lightmapupdateflags;
14528
14529         // update light styles on this submodel
14530         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14531         {
14532                 model_brush_lightstyleinfo_t *style;
14533                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14534                 {
14535                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14536                         {
14537                                 int *list = style->surfacelist;
14538                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14539                                 for (j = 0;j < style->numsurfaces;j++)
14540                                         update[list[j]] = true;
14541                         }
14542                 }
14543         }
14544
14545         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14546
14547         if (debug)
14548         {
14549                 R_DrawDebugModel();
14550                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14551                 return;
14552         }
14553
14554         rsurface.lightmaptexture = NULL;
14555         rsurface.deluxemaptexture = NULL;
14556         rsurface.uselightmaptexture = false;
14557         rsurface.texture = NULL;
14558         rsurface.rtlight = NULL;
14559         numsurfacelist = 0;
14560         // add visible surfaces to draw list
14561         for (i = 0;i < model->nummodelsurfaces;i++)
14562         {
14563                 j = model->sortedmodelsurfaces[i];
14564                 if (r_refdef.viewcache.world_surfacevisible[j])
14565                         r_surfacelist[numsurfacelist++] = surfaces + j;
14566         }
14567         // update lightmaps if needed
14568         if (model->brushq1.firstrender)
14569         {
14570                 model->brushq1.firstrender = false;
14571                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14572                         if (update[j])
14573                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14574         }
14575         else if (update)
14576         {
14577                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14578                         if (r_refdef.viewcache.world_surfacevisible[j])
14579                                 if (update[j])
14580                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14581         }
14582         // don't do anything if there were no surfaces
14583         if (!numsurfacelist)
14584         {
14585                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14586                 return;
14587         }
14588         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14589
14590         // add to stats if desired
14591         if (r_speeds.integer && !skysurfaces && !depthonly)
14592         {
14593                 r_refdef.stats.world_surfaces += numsurfacelist;
14594                 for (j = 0;j < numsurfacelist;j++)
14595                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14596         }
14597
14598         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14599 }
14600
14601 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14602 {
14603         int i, j, endj, flagsmask;
14604         dp_model_t *model = ent->model;
14605         msurface_t *surfaces;
14606         unsigned char *update;
14607         int numsurfacelist = 0;
14608         if (model == NULL)
14609                 return;
14610
14611         if (r_maxsurfacelist < model->num_surfaces)
14612         {
14613                 r_maxsurfacelist = model->num_surfaces;
14614                 if (r_surfacelist)
14615                         Mem_Free((msurface_t **)r_surfacelist);
14616                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14617         }
14618
14619         // if the model is static it doesn't matter what value we give for
14620         // wantnormals and wanttangents, so this logic uses only rules applicable
14621         // to a model, knowing that they are meaningless otherwise
14622         if (ent == r_refdef.scene.worldentity)
14623                 RSurf_ActiveWorldEntity();
14624         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14625                 RSurf_ActiveModelEntity(ent, false, false, false);
14626         else if (prepass)
14627                 RSurf_ActiveModelEntity(ent, true, true, true);
14628         else if (depthonly)
14629         {
14630                 switch (vid.renderpath)
14631                 {
14632                 case RENDERPATH_GL20:
14633                 case RENDERPATH_CGGL:
14634                 case RENDERPATH_D3D9:
14635                 case RENDERPATH_D3D10:
14636                 case RENDERPATH_D3D11:
14637                 case RENDERPATH_SOFT:
14638                 case RENDERPATH_GLES2:
14639                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14640                         break;
14641                 case RENDERPATH_GL13:
14642                 case RENDERPATH_GL11:
14643                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14644                         break;
14645                 }
14646         }
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         surfaces = model->data_surfaces;
14668         update = model->brushq1.lightmapupdateflags;
14669
14670         // update light styles
14671         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14672         {
14673                 model_brush_lightstyleinfo_t *style;
14674                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14675                 {
14676                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14677                         {
14678                                 int *list = style->surfacelist;
14679                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14680                                 for (j = 0;j < style->numsurfaces;j++)
14681                                         update[list[j]] = true;
14682                         }
14683                 }
14684         }
14685
14686         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14687
14688         if (debug)
14689         {
14690                 R_DrawDebugModel();
14691                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14692                 return;
14693         }
14694
14695         rsurface.lightmaptexture = NULL;
14696         rsurface.deluxemaptexture = NULL;
14697         rsurface.uselightmaptexture = false;
14698         rsurface.texture = NULL;
14699         rsurface.rtlight = NULL;
14700         numsurfacelist = 0;
14701         // add visible surfaces to draw list
14702         for (i = 0;i < model->nummodelsurfaces;i++)
14703                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14704         // don't do anything if there were no surfaces
14705         if (!numsurfacelist)
14706         {
14707                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14708                 return;
14709         }
14710         // update lightmaps if needed
14711         if (update)
14712         {
14713                 int updated = 0;
14714                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14715                 {
14716                         if (update[j])
14717                         {
14718                                 updated++;
14719                                 R_BuildLightMap(ent, surfaces + j);
14720                         }
14721                 }
14722         }
14723         if (update)
14724                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14725                         if (update[j])
14726                                 R_BuildLightMap(ent, surfaces + j);
14727         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14728
14729         // add to stats if desired
14730         if (r_speeds.integer && !skysurfaces && !depthonly)
14731         {
14732                 r_refdef.stats.entities_surfaces += numsurfacelist;
14733                 for (j = 0;j < numsurfacelist;j++)
14734                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14735         }
14736
14737         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14738 }
14739
14740 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14741 {
14742         static texture_t texture;
14743         static msurface_t surface;
14744         const msurface_t *surfacelist = &surface;
14745
14746         // fake enough texture and surface state to render this geometry
14747
14748         texture.update_lastrenderframe = -1; // regenerate this texture
14749         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14750         texture.currentskinframe = skinframe;
14751         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14752         texture.offsetmapping = OFFSETMAPPING_OFF;
14753         texture.offsetscale = 1;
14754         texture.specularscalemod = 1;
14755         texture.specularpowermod = 1;
14756
14757         surface.texture = &texture;
14758         surface.num_triangles = numtriangles;
14759         surface.num_firsttriangle = firsttriangle;
14760         surface.num_vertices = numvertices;
14761         surface.num_firstvertex = firstvertex;
14762
14763         // now render it
14764         rsurface.texture = R_GetCurrentTexture(surface.texture);
14765         rsurface.lightmaptexture = NULL;
14766         rsurface.deluxemaptexture = NULL;
14767         rsurface.uselightmaptexture = false;
14768         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14769 }
14770
14771 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)
14772 {
14773         static msurface_t surface;
14774         const msurface_t *surfacelist = &surface;
14775
14776         // fake enough texture and surface state to render this geometry
14777         surface.texture = texture;
14778         surface.num_triangles = numtriangles;
14779         surface.num_firsttriangle = firsttriangle;
14780         surface.num_vertices = numvertices;
14781         surface.num_firstvertex = firstvertex;
14782
14783         // now render it
14784         rsurface.texture = R_GetCurrentTexture(surface.texture);
14785         rsurface.lightmaptexture = NULL;
14786         rsurface.deluxemaptexture = NULL;
14787         rsurface.uselightmaptexture = false;
14788         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14789 }