]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
added qglVertexAttrib and other missing functions on GLES2 path
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
96
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
100
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
119 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
120
121 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
122 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
123 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
124 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
125 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
126 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
127 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
128 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
129
130 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
131 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
132
133 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
138
139 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
140 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
141 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
142
143 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
144 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
145 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
146 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
147 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
148 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
149 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
150 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
151 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
152 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
153 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
154 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
155 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
156
157 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
158 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
159 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
160 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
161 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
162 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
163
164 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
165 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
166 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
167 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
168
169 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
170 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
171 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
172 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
173 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
174 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
175 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
176
177 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
178 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
179 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
180 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
181
182 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
183
184 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
185
186 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
187
188 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
189 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
190 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
191 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
192 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
193 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
194 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
195 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
196 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
197
198 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
199 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
200
201 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
202
203 extern cvar_t v_glslgamma;
204
205 extern qboolean v_flipped_state;
206
207 static struct r_bloomstate_s
208 {
209         qboolean enabled;
210         qboolean hdr;
211
212         int bloomwidth, bloomheight;
213
214         int screentexturewidth, screentextureheight;
215         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
216
217         int bloomtexturewidth, bloomtextureheight;
218         rtexture_t *texture_bloom;
219
220         // arrays for rendering the screen passes
221         float screentexcoord2f[8];
222         float bloomtexcoord2f[8];
223         float offsettexcoord2f[8];
224
225         r_viewport_t viewport;
226 }
227 r_bloomstate;
228
229 r_waterstate_t r_waterstate;
230
231 /// shadow volume bsp struct with automatically growing nodes buffer
232 svbsp_t r_svbsp;
233
234 rtexture_t *r_texture_blanknormalmap;
235 rtexture_t *r_texture_white;
236 rtexture_t *r_texture_grey128;
237 rtexture_t *r_texture_black;
238 rtexture_t *r_texture_notexture;
239 rtexture_t *r_texture_whitecube;
240 rtexture_t *r_texture_normalizationcube;
241 rtexture_t *r_texture_fogattenuation;
242 rtexture_t *r_texture_fogheighttexture;
243 rtexture_t *r_texture_gammaramps;
244 unsigned int r_texture_gammaramps_serial;
245 //rtexture_t *r_texture_fogintensity;
246 rtexture_t *r_texture_reflectcube;
247
248 // TODO: hash lookups?
249 typedef struct cubemapinfo_s
250 {
251         char basename[64];
252         rtexture_t *texture;
253 }
254 cubemapinfo_t;
255
256 int r_texture_numcubemaps;
257 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
258
259 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
260 unsigned int r_numqueries;
261 unsigned int r_maxqueries;
262
263 typedef struct r_qwskincache_s
264 {
265         char name[MAX_QPATH];
266         skinframe_t *skinframe;
267 }
268 r_qwskincache_t;
269
270 static r_qwskincache_t *r_qwskincache;
271 static int r_qwskincache_size;
272
273 /// vertex coordinates for a quad that covers the screen exactly
274 extern const float r_screenvertex3f[12];
275 extern const float r_d3dscreenvertex3f[12];
276 const float r_screenvertex3f[12] =
277 {
278         0, 0, 0,
279         1, 0, 0,
280         1, 1, 0,
281         0, 1, 0
282 };
283 const float r_d3dscreenvertex3f[12] =
284 {
285         0, 1, 0,
286         1, 1, 0,
287         1, 0, 0,
288         0, 0, 0
289 };
290
291 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
292 {
293         int i;
294         for (i = 0;i < verts;i++)
295         {
296                 out[0] = in[0] * r;
297                 out[1] = in[1] * g;
298                 out[2] = in[2] * b;
299                 out[3] = in[3];
300                 in += 4;
301                 out += 4;
302         }
303 }
304
305 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
306 {
307         int i;
308         for (i = 0;i < verts;i++)
309         {
310                 out[0] = r;
311                 out[1] = g;
312                 out[2] = b;
313                 out[3] = a;
314                 out += 4;
315         }
316 }
317
318 // FIXME: move this to client?
319 void FOG_clear(void)
320 {
321         if (gamemode == GAME_NEHAHRA)
322         {
323                 Cvar_Set("gl_fogenable", "0");
324                 Cvar_Set("gl_fogdensity", "0.2");
325                 Cvar_Set("gl_fogred", "0.3");
326                 Cvar_Set("gl_foggreen", "0.3");
327                 Cvar_Set("gl_fogblue", "0.3");
328         }
329         r_refdef.fog_density = 0;
330         r_refdef.fog_red = 0;
331         r_refdef.fog_green = 0;
332         r_refdef.fog_blue = 0;
333         r_refdef.fog_alpha = 1;
334         r_refdef.fog_start = 0;
335         r_refdef.fog_end = 16384;
336         r_refdef.fog_height = 1<<30;
337         r_refdef.fog_fadedepth = 128;
338         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
339 }
340
341 static void R_BuildBlankTextures(void)
342 {
343         unsigned char data[4];
344         data[2] = 128; // normal X
345         data[1] = 128; // normal Y
346         data[0] = 255; // normal Z
347         data[3] = 128; // height
348         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
349         data[0] = 255;
350         data[1] = 255;
351         data[2] = 255;
352         data[3] = 255;
353         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
354         data[0] = 128;
355         data[1] = 128;
356         data[2] = 128;
357         data[3] = 255;
358         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
359         data[0] = 0;
360         data[1] = 0;
361         data[2] = 0;
362         data[3] = 255;
363         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
364 }
365
366 static void R_BuildNoTexture(void)
367 {
368         int x, y;
369         unsigned char pix[16][16][4];
370         // this makes a light grey/dark grey checkerboard texture
371         for (y = 0;y < 16;y++)
372         {
373                 for (x = 0;x < 16;x++)
374                 {
375                         if ((y < 8) ^ (x < 8))
376                         {
377                                 pix[y][x][0] = 128;
378                                 pix[y][x][1] = 128;
379                                 pix[y][x][2] = 128;
380                                 pix[y][x][3] = 255;
381                         }
382                         else
383                         {
384                                 pix[y][x][0] = 64;
385                                 pix[y][x][1] = 64;
386                                 pix[y][x][2] = 64;
387                                 pix[y][x][3] = 255;
388                         }
389                 }
390         }
391         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
392 }
393
394 static void R_BuildWhiteCube(void)
395 {
396         unsigned char data[6*1*1*4];
397         memset(data, 255, sizeof(data));
398         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
399 }
400
401 static void R_BuildNormalizationCube(void)
402 {
403         int x, y, side;
404         vec3_t v;
405         vec_t s, t, intensity;
406 #define NORMSIZE 64
407         unsigned char *data;
408         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
409         for (side = 0;side < 6;side++)
410         {
411                 for (y = 0;y < NORMSIZE;y++)
412                 {
413                         for (x = 0;x < NORMSIZE;x++)
414                         {
415                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
416                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
417                                 switch(side)
418                                 {
419                                 default:
420                                 case 0:
421                                         v[0] = 1;
422                                         v[1] = -t;
423                                         v[2] = -s;
424                                         break;
425                                 case 1:
426                                         v[0] = -1;
427                                         v[1] = -t;
428                                         v[2] = s;
429                                         break;
430                                 case 2:
431                                         v[0] = s;
432                                         v[1] = 1;
433                                         v[2] = t;
434                                         break;
435                                 case 3:
436                                         v[0] = s;
437                                         v[1] = -1;
438                                         v[2] = -t;
439                                         break;
440                                 case 4:
441                                         v[0] = s;
442                                         v[1] = -t;
443                                         v[2] = 1;
444                                         break;
445                                 case 5:
446                                         v[0] = -s;
447                                         v[1] = -t;
448                                         v[2] = -1;
449                                         break;
450                                 }
451                                 intensity = 127.0f / sqrt(DotProduct(v, v));
452                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
453                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
454                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
455                                 data[((side*64+y)*64+x)*4+3] = 255;
456                         }
457                 }
458         }
459         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
460         Mem_Free(data);
461 }
462
463 static void R_BuildFogTexture(void)
464 {
465         int x, b;
466 #define FOGWIDTH 256
467         unsigned char data1[FOGWIDTH][4];
468         //unsigned char data2[FOGWIDTH][4];
469         double d, r, alpha;
470
471         r_refdef.fogmasktable_start = r_refdef.fog_start;
472         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
473         r_refdef.fogmasktable_range = r_refdef.fogrange;
474         r_refdef.fogmasktable_density = r_refdef.fog_density;
475
476         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
477         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
478         {
479                 d = (x * r - r_refdef.fogmasktable_start);
480                 if(developer_extra.integer)
481                         Con_DPrintf("%f ", d);
482                 d = max(0, d);
483                 if (r_fog_exp2.integer)
484                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
485                 else
486                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
487                 if(developer_extra.integer)
488                         Con_DPrintf(" : %f ", alpha);
489                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
490                 if(developer_extra.integer)
491                         Con_DPrintf(" = %f\n", alpha);
492                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
493         }
494
495         for (x = 0;x < FOGWIDTH;x++)
496         {
497                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
498                 data1[x][0] = b;
499                 data1[x][1] = b;
500                 data1[x][2] = b;
501                 data1[x][3] = 255;
502                 //data2[x][0] = 255 - b;
503                 //data2[x][1] = 255 - b;
504                 //data2[x][2] = 255 - b;
505                 //data2[x][3] = 255;
506         }
507         if (r_texture_fogattenuation)
508         {
509                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
510                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
511         }
512         else
513         {
514                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
515                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
516         }
517 }
518
519 static void R_BuildFogHeightTexture(void)
520 {
521         unsigned char *inpixels;
522         int size;
523         int x;
524         int y;
525         int j;
526         float c[4];
527         float f;
528         inpixels = NULL;
529         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
530         if (r_refdef.fogheighttexturename[0])
531                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
532         if (!inpixels)
533         {
534                 r_refdef.fog_height_tablesize = 0;
535                 if (r_texture_fogheighttexture)
536                         R_FreeTexture(r_texture_fogheighttexture);
537                 r_texture_fogheighttexture = NULL;
538                 if (r_refdef.fog_height_table2d)
539                         Mem_Free(r_refdef.fog_height_table2d);
540                 r_refdef.fog_height_table2d = NULL;
541                 if (r_refdef.fog_height_table1d)
542                         Mem_Free(r_refdef.fog_height_table1d);
543                 r_refdef.fog_height_table1d = NULL;
544                 return;
545         }
546         size = image_width;
547         r_refdef.fog_height_tablesize = size;
548         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
549         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
550         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
551         Mem_Free(inpixels);
552         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
553         // average fog color table accounting for every fog layer between a point
554         // and the camera.  (Note: attenuation is handled separately!)
555         for (y = 0;y < size;y++)
556         {
557                 for (x = 0;x < size;x++)
558                 {
559                         Vector4Clear(c);
560                         f = 0;
561                         if (x < y)
562                         {
563                                 for (j = x;j <= y;j++)
564                                 {
565                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
566                                         f++;
567                                 }
568                         }
569                         else
570                         {
571                                 for (j = x;j >= y;j--)
572                                 {
573                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
574                                         f++;
575                                 }
576                         }
577                         f = 1.0f / f;
578                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
579                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
580                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
581                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
582                 }
583         }
584         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
585 }
586
587 //=======================================================================================================================================================
588
589 static const char *builtinshaderstring =
590 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
591 "// written by Forest 'LordHavoc' Hale\n"
592 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
593 "\n"
594 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
595 "# define USEFOG\n"
596 "#endif\n"
597 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
598 "#define USELIGHTMAP\n"
599 "#endif\n"
600 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
601 "#define USEEYEVECTOR\n"
602 "#endif\n"
603 "\n"
604 "#ifdef USESHADOWMAP2D\n"
605 "# ifdef GL_EXT_gpu_shader4\n"
606 "#   extension GL_EXT_gpu_shader4 : enable\n"
607 "# endif\n"
608 "# ifdef GL_ARB_texture_gather\n"
609 "#   extension GL_ARB_texture_gather : enable\n"
610 "# else\n"
611 "#   ifdef GL_AMD_texture_texture4\n"
612 "#     extension GL_AMD_texture_texture4 : enable\n"
613 "#   endif\n"
614 "# endif\n"
615 "#endif\n"
616 "\n"
617 "//#ifdef USESHADOWSAMPLER\n"
618 "//# extension GL_ARB_shadow : enable\n"
619 "//#endif\n"
620 "\n"
621 "//#ifdef __GLSL_CG_DATA_TYPES\n"
622 "//# define myhalf half\n"
623 "//# define myhalf2 half2\n"
624 "//# define myhalf3 half3\n"
625 "//# define myhalf4 half4\n"
626 "//#else\n"
627 "# define myhalf float\n"
628 "# define myhalf2 vec2\n"
629 "# define myhalf3 vec3\n"
630 "# define myhalf4 vec4\n"
631 "//#endif\n"
632 "\n"
633 "#ifdef VERTEX_SHADER\n"
634 "uniform mat4 ModelViewProjectionMatrix;\n"
635 "#endif\n"
636 "\n"
637 "#ifdef MODE_DEPTH_OR_SHADOW\n"
638 "#ifdef VERTEX_SHADER\n"
639 "void main(void)\n"
640 "{\n"
641 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
642 "}\n"
643 "#endif\n"
644 "#else // !MODE_DEPTH_ORSHADOW\n"
645 "\n"
646 "\n"
647 "\n"
648 "\n"
649 "#ifdef MODE_SHOWDEPTH\n"
650 "#ifdef VERTEX_SHADER\n"
651 "void main(void)\n"
652 "{\n"
653 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
654 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
655 "}\n"
656 "#endif\n"
657 "\n"
658 "#ifdef FRAGMENT_SHADER\n"
659 "void main(void)\n"
660 "{\n"
661 "       gl_FragColor = gl_Color;\n"
662 "}\n"
663 "#endif\n"
664 "#else // !MODE_SHOWDEPTH\n"
665 "\n"
666 "\n"
667 "\n"
668 "\n"
669 "#ifdef MODE_POSTPROCESS\n"
670 "varying vec2 TexCoord1;\n"
671 "varying vec2 TexCoord2;\n"
672 "\n"
673 "#ifdef VERTEX_SHADER\n"
674 "void main(void)\n"
675 "{\n"
676 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
677 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
678 "#ifdef USEBLOOM\n"
679 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
680 "#endif\n"
681 "}\n"
682 "#endif\n"
683 "\n"
684 "#ifdef FRAGMENT_SHADER\n"
685 "uniform sampler2D Texture_First;\n"
686 "#ifdef USEBLOOM\n"
687 "uniform sampler2D Texture_Second;\n"
688 "uniform vec4 BloomColorSubtract;\n"
689 "#endif\n"
690 "#ifdef USEGAMMARAMPS\n"
691 "uniform sampler2D Texture_GammaRamps;\n"
692 "#endif\n"
693 "#ifdef USESATURATION\n"
694 "uniform float Saturation;\n"
695 "#endif\n"
696 "#ifdef USEVIEWTINT\n"
697 "uniform vec4 ViewTintColor;\n"
698 "#endif\n"
699 "//uncomment these if you want to use them:\n"
700 "uniform vec4 UserVec1;\n"
701 "uniform vec4 UserVec2;\n"
702 "// uniform vec4 UserVec3;\n"
703 "// uniform vec4 UserVec4;\n"
704 "// uniform float ClientTime;\n"
705 "uniform vec2 PixelSize;\n"
706 "void main(void)\n"
707 "{\n"
708 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
709 "#ifdef USEBLOOM\n"
710 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
711 "#endif\n"
712 "#ifdef USEVIEWTINT\n"
713 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
714 "#endif\n"
715 "\n"
716 "#ifdef USEPOSTPROCESSING\n"
717 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
718 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
719 "       float sobel = 1.0;\n"
720 "       // vec2 ts = textureSize(Texture_First, 0);\n"
721 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
722 "       vec2 px = PixelSize;\n"
723 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
724 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
725 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
726 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
727 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
728 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
729 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
730 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
731 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
732 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
733 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
734 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
735 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
736 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
737 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
738 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
739 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
740 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
741 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
742 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
743 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
744 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
745 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
746 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
747 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
748 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
749 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
750 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
751 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
752 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
753 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
754 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
755 "#endif\n"
756 "\n"
757 "#ifdef USESATURATION\n"
758 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
759 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
760 "       // 'vampire sight' effect, wheres red is compensated\n"
761 "       #ifdef SATURATION_REDCOMPENSATE\n"
762 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
763 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
764 "               gl_FragColor.r += rboost;\n"
765 "       #else\n"
766 "               // normal desaturation\n"
767 "               //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
768 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
769 "       #endif\n"
770 "#endif\n"
771 "\n"
772 "#ifdef USEGAMMARAMPS\n"
773 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
774 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
775 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
776 "#endif\n"
777 "}\n"
778 "#endif\n"
779 "#else // !MODE_POSTPROCESS\n"
780 "\n"
781 "\n"
782 "\n"
783 "\n"
784 "#ifdef MODE_GENERIC\n"
785 "#ifdef USEDIFFUSE\n"
786 "varying vec2 TexCoord1;\n"
787 "#endif\n"
788 "#ifdef USESPECULAR\n"
789 "varying vec2 TexCoord2;\n"
790 "#endif\n"
791 "#ifdef VERTEX_SHADER\n"
792 "void main(void)\n"
793 "{\n"
794 "       gl_FrontColor = gl_Color;\n"
795 "#ifdef USEDIFFUSE\n"
796 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
797 "#endif\n"
798 "#ifdef USESPECULAR\n"
799 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
800 "#endif\n"
801 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
802 "}\n"
803 "#endif\n"
804 "\n"
805 "#ifdef FRAGMENT_SHADER\n"
806 "#ifdef USEDIFFUSE\n"
807 "uniform sampler2D Texture_First;\n"
808 "#endif\n"
809 "#ifdef USESPECULAR\n"
810 "uniform sampler2D Texture_Second;\n"
811 "#endif\n"
812 "\n"
813 "void main(void)\n"
814 "{\n"
815 "#ifdef USEVIEWTINT\n"
816 "       gl_FragColor = gl_Color;\n"
817 "#else\n"
818 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
819 "#endif\n"
820 "#ifdef USEDIFFUSE\n"
821 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
822 "#endif\n"
823 "\n"
824 "#ifdef USESPECULAR\n"
825 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
826 "# ifdef USECOLORMAPPING\n"
827 "       gl_FragColor *= tex2;\n"
828 "# endif\n"
829 "# ifdef USEGLOW\n"
830 "       gl_FragColor += tex2;\n"
831 "# endif\n"
832 "# ifdef USEVERTEXTEXTUREBLEND\n"
833 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
834 "# endif\n"
835 "#endif\n"
836 "}\n"
837 "#endif\n"
838 "#else // !MODE_GENERIC\n"
839 "\n"
840 "\n"
841 "\n"
842 "\n"
843 "#ifdef MODE_BLOOMBLUR\n"
844 "varying TexCoord;\n"
845 "#ifdef VERTEX_SHADER\n"
846 "void main(void)\n"
847 "{\n"
848 "       gl_FrontColor = gl_Color;\n"
849 "       TexCoord = gl_MultiTexCoord0.xy;\n"
850 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
851 "}\n"
852 "#endif\n"
853 "\n"
854 "#ifdef FRAGMENT_SHADER\n"
855 "uniform sampler2D Texture_First;\n"
856 "uniform vec4 BloomBlur_Parameters;\n"
857 "\n"
858 "void main(void)\n"
859 "{\n"
860 "       int i;\n"
861 "       vec2 tc = TexCoord;\n"
862 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
863 "       tc += BloomBlur_Parameters.xy;\n"
864 "       for (i = 1;i < SAMPLES;i++)\n"
865 "       {\n"
866 "               color += texture2D(Texture_First, tc).rgb;\n"
867 "               tc += BloomBlur_Parameters.xy;\n"
868 "       }\n"
869 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
870 "}\n"
871 "#endif\n"
872 "#else // !MODE_BLOOMBLUR\n"
873 "#ifdef MODE_REFRACTION\n"
874 "varying vec2 TexCoord;\n"
875 "varying vec4 ModelViewProjectionPosition;\n"
876 "uniform mat4 TexMatrix;\n"
877 "#ifdef VERTEX_SHADER\n"
878 "\n"
879 "void main(void)\n"
880 "{\n"
881 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
882 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
883 "       ModelViewProjectionPosition = gl_Position;\n"
884 "}\n"
885 "#endif\n"
886 "\n"
887 "#ifdef FRAGMENT_SHADER\n"
888 "uniform sampler2D Texture_Normal;\n"
889 "uniform sampler2D Texture_Refraction;\n"
890 "uniform sampler2D Texture_Reflection;\n"
891 "\n"
892 "uniform vec4 DistortScaleRefractReflect;\n"
893 "uniform vec4 ScreenScaleRefractReflect;\n"
894 "uniform vec4 ScreenCenterRefractReflect;\n"
895 "uniform vec4 RefractColor;\n"
896 "uniform vec4 ReflectColor;\n"
897 "uniform float ReflectFactor;\n"
898 "uniform float ReflectOffset;\n"
899 "\n"
900 "void main(void)\n"
901 "{\n"
902 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
903 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
904 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
905 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
906 "       // FIXME temporary hack to detect the case that the reflection\n"
907 "       // gets blackened at edges due to leaving the area that contains actual\n"
908 "       // content.\n"
909 "       // Remove this 'ack once we have a better way to stop this thing from\n"
910 "       // 'appening.\n"
911 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
912 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
913 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
914 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
915 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
916 "       gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
917 "}\n"
918 "#endif\n"
919 "#else // !MODE_REFRACTION\n"
920 "\n"
921 "\n"
922 "\n"
923 "\n"
924 "#ifdef MODE_WATER\n"
925 "varying vec2 TexCoord;\n"
926 "varying vec3 EyeVector;\n"
927 "varying vec4 ModelViewProjectionPosition;\n"
928 "#ifdef VERTEX_SHADER\n"
929 "uniform vec3 EyePosition;\n"
930 "uniform mat4 TexMatrix;\n"
931 "\n"
932 "void main(void)\n"
933 "{\n"
934 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
935 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
936 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
937 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
938 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
939 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
940 "       ModelViewProjectionPosition = gl_Position;\n"
941 "}\n"
942 "#endif\n"
943 "\n"
944 "#ifdef FRAGMENT_SHADER\n"
945 "uniform sampler2D Texture_Normal;\n"
946 "uniform sampler2D Texture_Refraction;\n"
947 "uniform sampler2D Texture_Reflection;\n"
948 "\n"
949 "uniform vec4 DistortScaleRefractReflect;\n"
950 "uniform vec4 ScreenScaleRefractReflect;\n"
951 "uniform vec4 ScreenCenterRefractReflect;\n"
952 "uniform vec4 RefractColor;\n"
953 "uniform vec4 ReflectColor;\n"
954 "uniform float ReflectFactor;\n"
955 "uniform float ReflectOffset;\n"
956 "uniform float ClientTime;\n"
957 "#ifdef USENORMALMAPSCROLLBLEND\n"
958 "uniform vec2 NormalmapScrollBlend;\n"
959 "#endif\n"
960 "\n"
961 "void main(void)\n"
962 "{\n"
963 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
964 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
965 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
966 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
967 "       // slight water animation via 2 layer scrolling (todo: tweak)\n"
968 "       #ifdef USENORMALMAPSCROLLBLEND\n"
969 "               vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
970 "               normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
971 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
972 "       #else\n"
973 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
974 "       #endif\n"
975 "       // FIXME temporary hack to detect the case that the reflection\n"
976 "       // gets blackened at edges due to leaving the area that contains actual\n"
977 "       // content.\n"
978 "       // Remove this 'ack once we have a better way to stop this thing from\n"
979 "       // 'appening.\n"
980 "       float f  = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
981 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
982 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
983 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
984 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
985 "       f  = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
986 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
987 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
988 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
989 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
990 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
991 "       gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
992 "}\n"
993 "#endif\n"
994 "#else // !MODE_WATER\n"
995 "\n"
996 "\n"
997 "\n"
998 "\n"
999 "// common definitions between vertex shader and fragment shader:\n"
1000 "\n"
1001 "varying vec2 TexCoord;\n"
1002 "#ifdef USEVERTEXTEXTUREBLEND\n"
1003 "varying vec2 TexCoord2;\n"
1004 "#endif\n"
1005 "#ifdef USELIGHTMAP\n"
1006 "varying vec2 TexCoordLightmap;\n"
1007 "#endif\n"
1008 "\n"
1009 "#ifdef MODE_LIGHTSOURCE\n"
1010 "varying vec3 CubeVector;\n"
1011 "#endif\n"
1012 "\n"
1013 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1014 "varying vec3 LightVector;\n"
1015 "#endif\n"
1016 "\n"
1017 "#ifdef USEEYEVECTOR\n"
1018 "varying vec3 EyeVector;\n"
1019 "#endif\n"
1020 "#ifdef USEFOG\n"
1021 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1022 "#endif\n"
1023 "\n"
1024 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1025 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1026 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1027 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1028 "#endif\n"
1029 "\n"
1030 "#ifdef USEREFLECTION\n"
1031 "varying vec4 ModelViewProjectionPosition;\n"
1032 "#endif\n"
1033 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1034 "uniform vec3 LightPosition;\n"
1035 "varying vec4 ModelViewPosition;\n"
1036 "#endif\n"
1037 "\n"
1038 "#ifdef MODE_LIGHTSOURCE\n"
1039 "uniform vec3 LightPosition;\n"
1040 "#endif\n"
1041 "uniform vec3 EyePosition;\n"
1042 "#ifdef MODE_LIGHTDIRECTION\n"
1043 "uniform vec3 LightDir;\n"
1044 "#endif\n"
1045 "uniform vec4 FogPlane;\n"
1046 "\n"
1047 "#ifdef USESHADOWMAPORTHO\n"
1048 "varying vec3 ShadowMapTC;\n"
1049 "#endif\n"
1050 "\n"
1051 "\n"
1052 "\n"
1053 "\n"
1054 "\n"
1055 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
1056 "\n"
1057 "// fragment shader specific:\n"
1058 "#ifdef FRAGMENT_SHADER\n"
1059 "\n"
1060 "uniform sampler2D Texture_Normal;\n"
1061 "uniform sampler2D Texture_Color;\n"
1062 "uniform sampler2D Texture_Gloss;\n"
1063 "#ifdef USEGLOW\n"
1064 "uniform sampler2D Texture_Glow;\n"
1065 "#endif\n"
1066 "#ifdef USEVERTEXTEXTUREBLEND\n"
1067 "uniform sampler2D Texture_SecondaryNormal;\n"
1068 "uniform sampler2D Texture_SecondaryColor;\n"
1069 "uniform sampler2D Texture_SecondaryGloss;\n"
1070 "#ifdef USEGLOW\n"
1071 "uniform sampler2D Texture_SecondaryGlow;\n"
1072 "#endif\n"
1073 "#endif\n"
1074 "#ifdef USECOLORMAPPING\n"
1075 "uniform sampler2D Texture_Pants;\n"
1076 "uniform sampler2D Texture_Shirt;\n"
1077 "#endif\n"
1078 "#ifdef USEFOG\n"
1079 "#ifdef USEFOGHEIGHTTEXTURE\n"
1080 "uniform sampler2D Texture_FogHeightTexture;\n"
1081 "#endif\n"
1082 "uniform sampler2D Texture_FogMask;\n"
1083 "#endif\n"
1084 "#ifdef USELIGHTMAP\n"
1085 "uniform sampler2D Texture_Lightmap;\n"
1086 "#endif\n"
1087 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1088 "uniform sampler2D Texture_Deluxemap;\n"
1089 "#endif\n"
1090 "#ifdef USEREFLECTION\n"
1091 "uniform sampler2D Texture_Reflection;\n"
1092 "#endif\n"
1093 "\n"
1094 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1095 "uniform sampler2D Texture_ScreenDepth;\n"
1096 "uniform sampler2D Texture_ScreenNormalMap;\n"
1097 "#endif\n"
1098 "#ifdef USEDEFERREDLIGHTMAP\n"
1099 "uniform sampler2D Texture_ScreenDiffuse;\n"
1100 "uniform sampler2D Texture_ScreenSpecular;\n"
1101 "#endif\n"
1102 "\n"
1103 "uniform myhalf3 Color_Pants;\n"
1104 "uniform myhalf3 Color_Shirt;\n"
1105 "uniform myhalf3 FogColor;\n"
1106 "\n"
1107 "#ifdef USEFOG\n"
1108 "uniform float FogRangeRecip;\n"
1109 "uniform float FogPlaneViewDist;\n"
1110 "uniform float FogHeightFade;\n"
1111 "vec3 FogVertex(vec3 surfacecolor)\n"
1112 "{\n"
1113 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1114 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1115 "       float fogfrac;\n"
1116 "#ifdef USEFOGHEIGHTTEXTURE\n"
1117 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1118 "       fogfrac = fogheightpixel.a;\n"
1119 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1120 "#else\n"
1121 "# ifdef USEFOGOUTSIDE\n"
1122 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1123 "# else\n"
1124 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1125 "# endif\n"
1126 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1127 "#endif\n"
1128 "}\n"
1129 "#endif\n"
1130 "\n"
1131 "#ifdef USEOFFSETMAPPING\n"
1132 "uniform float OffsetMapping_Scale;\n"
1133 "vec2 OffsetMapping(vec2 TexCoord)\n"
1134 "{\n"
1135 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1136 "       // 14 sample relief mapping: linear search and then binary search\n"
1137 "       // this basically steps forward a small amount repeatedly until it finds\n"
1138 "       // itself inside solid, then jitters forward and back using decreasing\n"
1139 "       // amounts to find the impact\n"
1140 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1141 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1142 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1143 "       vec3 RT = vec3(TexCoord, 1);\n"
1144 "       OffsetVector *= 0.1;\n"
1145 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1146 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1147 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1148 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1149 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1150 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1151 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1152 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1153 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1154 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1155 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1156 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1157 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1158 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1159 "       return RT.xy;\n"
1160 "#else\n"
1161 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1162 "       // this basically moves forward the full distance, and then backs up based\n"
1163 "       // on height of samples\n"
1164 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1165 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1166 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1167 "       TexCoord += OffsetVector;\n"
1168 "       OffsetVector *= 0.5;\n"
1169 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1170 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1171 "       return TexCoord;\n"
1172 "#endif\n"
1173 "}\n"
1174 "#endif // USEOFFSETMAPPING\n"
1175 "\n"
1176 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1177 "uniform sampler2D Texture_Attenuation;\n"
1178 "uniform samplerCube Texture_Cube;\n"
1179 "#endif\n"
1180 "\n"
1181 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1182 "\n"
1183 "#ifdef USESHADOWMAP2D\n"
1184 "# ifdef USESHADOWSAMPLER\n"
1185 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1186 "# else\n"
1187 "uniform sampler2D Texture_ShadowMap2D;\n"
1188 "# endif\n"
1189 "#endif\n"
1190 "\n"
1191 "#ifdef USESHADOWMAPVSDCT\n"
1192 "uniform samplerCube Texture_CubeProjection;\n"
1193 "#endif\n"
1194 "\n"
1195 "#if defined(USESHADOWMAP2D)\n"
1196 "uniform vec2 ShadowMap_TextureScale;\n"
1197 "uniform vec4 ShadowMap_Parameters;\n"
1198 "#endif\n"
1199 "\n"
1200 "#if defined(USESHADOWMAP2D)\n"
1201 "# ifdef USESHADOWMAPORTHO\n"
1202 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1203 "# else\n"
1204 "#  ifdef USESHADOWMAPVSDCT\n"
1205 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1206 "{\n"
1207 "       vec3 adir = abs(dir);\n"
1208 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1209 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1210 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1211 "}\n"
1212 "#  else\n"
1213 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1214 "{\n"
1215 "       vec3 adir = abs(dir);\n"
1216 "       float ma = adir.z;\n"
1217 "       vec4 proj = vec4(dir, 2.5);\n"
1218 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1219 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1220 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1221 "       return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1222 "}\n"
1223 "#  endif\n"
1224 "# endif\n"
1225 "#endif // defined(USESHADOWMAP2D)\n"
1226 "\n"
1227 "# ifdef USESHADOWMAP2D\n"
1228 "float ShadowMapCompare(vec3 dir)\n"
1229 "{\n"
1230 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1231 "       float f;\n"
1232 "\n"
1233 "#  ifdef USESHADOWSAMPLER\n"
1234 "#    ifdef USESHADOWMAPPCF\n"
1235 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1236 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1237 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1238 "#    else\n"
1239 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1240 "#    endif\n"
1241 "#  else\n"
1242 "#    ifdef USESHADOWMAPPCF\n"
1243 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1244 "#      ifdef GL_ARB_texture_gather\n"
1245 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1246 "#      else\n"
1247 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1248 "#      endif\n"
1249 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1250 "#      if USESHADOWMAPPCF > 1\n"
1251 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1252 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1253 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1254 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1255 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1256 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1257 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1258 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1259 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1260 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1261 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1262 "       locols.yz += group2.ab;\n"
1263 "       hicols.yz += group8.rg;\n"
1264 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1265 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1266 "                               mix(locols, hicols, offset.y);\n"
1267 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1268 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1269 "       f = dot(cols, vec4(1.0/25.0));\n"
1270 "#      else\n"
1271 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1272 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1273 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1274 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1275 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1276 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1277 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1278 "#      endif\n"
1279 "#     else\n"
1280 "#      ifdef GL_EXT_gpu_shader4\n"
1281 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1282 "#      else\n"
1283 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1284 "#      endif\n"
1285 "#      if USESHADOWMAPPCF > 1\n"
1286 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1287 "       center *= ShadowMap_TextureScale;\n"
1288 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1289 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1290 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1291 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1292 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1293 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1294 "#      else\n"
1295 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1296 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1297 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1298 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1299 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1300 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1301 "#      endif\n"
1302 "#     endif\n"
1303 "#    else\n"
1304 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1305 "#    endif\n"
1306 "#  endif\n"
1307 "#  ifdef USESHADOWMAPORTHO\n"
1308 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1309 "#  else\n"
1310 "       return f;\n"
1311 "#  endif\n"
1312 "}\n"
1313 "# endif\n"
1314 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1315 "#endif // FRAGMENT_SHADER\n"
1316 "\n"
1317 "\n"
1318 "\n"
1319 "\n"
1320 "#ifdef MODE_DEFERREDGEOMETRY\n"
1321 "#ifdef VERTEX_SHADER\n"
1322 "uniform mat4 TexMatrix;\n"
1323 "#ifdef USEVERTEXTEXTUREBLEND\n"
1324 "uniform mat4 BackgroundTexMatrix;\n"
1325 "#endif\n"
1326 "uniform mat4 ModelViewMatrix;\n"
1327 "void main(void)\n"
1328 "{\n"
1329 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1330 "#ifdef USEVERTEXTEXTUREBLEND\n"
1331 "       gl_FrontColor = gl_Color;\n"
1332 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1333 "#endif\n"
1334 "\n"
1335 "       // transform unnormalized eye direction into tangent space\n"
1336 "#ifdef USEOFFSETMAPPING\n"
1337 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1338 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1339 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1340 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1341 "#endif\n"
1342 "\n"
1343 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1344 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1345 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1346 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1347 "}\n"
1348 "#endif // VERTEX_SHADER\n"
1349 "\n"
1350 "#ifdef FRAGMENT_SHADER\n"
1351 "void main(void)\n"
1352 "{\n"
1353 "#ifdef USEOFFSETMAPPING\n"
1354 "       // apply offsetmapping\n"
1355 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1356 "#define TexCoord TexCoordOffset\n"
1357 "#endif\n"
1358 "\n"
1359 "#ifdef USEALPHAKILL\n"
1360 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1361 "               discard;\n"
1362 "#endif\n"
1363 "\n"
1364 "#ifdef USEVERTEXTEXTUREBLEND\n"
1365 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1366 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1367 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1368 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1369 "#endif\n"
1370 "\n"
1371 "#ifdef USEVERTEXTEXTUREBLEND\n"
1372 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1373 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1374 "#else\n"
1375 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1376 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1377 "#endif\n"
1378 "\n"
1379 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1380 "}\n"
1381 "#endif // FRAGMENT_SHADER\n"
1382 "#else // !MODE_DEFERREDGEOMETRY\n"
1383 "\n"
1384 "\n"
1385 "\n"
1386 "\n"
1387 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1388 "#ifdef VERTEX_SHADER\n"
1389 "uniform mat4 ModelViewMatrix;\n"
1390 "void main(void)\n"
1391 "{\n"
1392 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1393 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1394 "}\n"
1395 "#endif // VERTEX_SHADER\n"
1396 "\n"
1397 "#ifdef FRAGMENT_SHADER\n"
1398 "uniform mat4 ViewToLight;\n"
1399 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1400 "uniform vec2 ScreenToDepth;\n"
1401 "uniform myhalf3 DeferredColor_Ambient;\n"
1402 "uniform myhalf3 DeferredColor_Diffuse;\n"
1403 "#ifdef USESPECULAR\n"
1404 "uniform myhalf3 DeferredColor_Specular;\n"
1405 "uniform myhalf SpecularPower;\n"
1406 "#endif\n"
1407 "uniform myhalf2 PixelToScreenTexCoord;\n"
1408 "void main(void)\n"
1409 "{\n"
1410 "       // calculate viewspace pixel position\n"
1411 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1412 "       vec3 position;\n"
1413 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1414 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1415 "       // decode viewspace pixel normal\n"
1416 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1417 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1418 "       // surfacenormal = pixel normal in viewspace\n"
1419 "       // LightVector = pixel to light in viewspace\n"
1420 "       // CubeVector = position in lightspace\n"
1421 "       // eyevector = pixel to view in viewspace\n"
1422 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1423 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1424 "#ifdef USEDIFFUSE\n"
1425 "       // calculate diffuse shading\n"
1426 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1427 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1428 "#endif\n"
1429 "#ifdef USESPECULAR\n"
1430 "       // calculate directional shading\n"
1431 "       vec3 eyevector = position * -1.0;\n"
1432 "#  ifdef USEEXACTSPECULARMATH\n"
1433 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1434 "#  else\n"
1435 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1436 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1437 "#  endif\n"
1438 "#endif\n"
1439 "\n"
1440 "#if defined(USESHADOWMAP2D)\n"
1441 "       fade *= ShadowMapCompare(CubeVector);\n"
1442 "#endif\n"
1443 "\n"
1444 "#ifdef USEDIFFUSE\n"
1445 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1446 "#else\n"
1447 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1448 "#endif\n"
1449 "#ifdef USESPECULAR\n"
1450 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1451 "#else\n"
1452 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1453 "#endif\n"
1454 "\n"
1455 "# ifdef USECUBEFILTER\n"
1456 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1457 "       gl_FragData[0].rgb *= cubecolor;\n"
1458 "       gl_FragData[1].rgb *= cubecolor;\n"
1459 "# endif\n"
1460 "}\n"
1461 "#endif // FRAGMENT_SHADER\n"
1462 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1463 "\n"
1464 "\n"
1465 "\n"
1466 "\n"
1467 "#ifdef VERTEX_SHADER\n"
1468 "uniform mat4 TexMatrix;\n"
1469 "#ifdef USEVERTEXTEXTUREBLEND\n"
1470 "uniform mat4 BackgroundTexMatrix;\n"
1471 "#endif\n"
1472 "#ifdef MODE_LIGHTSOURCE\n"
1473 "uniform mat4 ModelToLight;\n"
1474 "#endif\n"
1475 "#ifdef USESHADOWMAPORTHO\n"
1476 "uniform mat4 ShadowMapMatrix;\n"
1477 "#endif\n"
1478 "void main(void)\n"
1479 "{\n"
1480 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1481 "       gl_FrontColor = gl_Color;\n"
1482 "#endif\n"
1483 "       // copy the surface texcoord\n"
1484 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1485 "#ifdef USEVERTEXTEXTUREBLEND\n"
1486 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1487 "#endif\n"
1488 "#ifdef USELIGHTMAP\n"
1489 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1490 "#endif\n"
1491 "\n"
1492 "#ifdef MODE_LIGHTSOURCE\n"
1493 "       // transform vertex position into light attenuation/cubemap space\n"
1494 "       // (-1 to +1 across the light box)\n"
1495 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1496 "\n"
1497 "# ifdef USEDIFFUSE\n"
1498 "       // transform unnormalized light direction into tangent space\n"
1499 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1500 "       //  normalize it per pixel)\n"
1501 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1502 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1503 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1504 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1505 "# endif\n"
1506 "#endif\n"
1507 "\n"
1508 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1509 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1510 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1511 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1512 "#endif\n"
1513 "\n"
1514 "       // transform unnormalized eye direction into tangent space\n"
1515 "#ifdef USEEYEVECTOR\n"
1516 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1517 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1518 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1519 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1520 "#endif\n"
1521 "\n"
1522 "#ifdef USEFOG\n"
1523 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1524 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1525 "#endif\n"
1526 "\n"
1527 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1528 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1529 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1530 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1531 "#endif\n"
1532 "\n"
1533 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1534 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1535 "\n"
1536 "#ifdef USESHADOWMAPORTHO\n"
1537 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1538 "#endif\n"
1539 "\n"
1540 "#ifdef USEREFLECTION\n"
1541 "       ModelViewProjectionPosition = gl_Position;\n"
1542 "#endif\n"
1543 "}\n"
1544 "#endif // VERTEX_SHADER\n"
1545 "\n"
1546 "\n"
1547 "\n"
1548 "\n"
1549 "#ifdef FRAGMENT_SHADER\n"
1550 "#ifdef USEDEFERREDLIGHTMAP\n"
1551 "uniform myhalf2 PixelToScreenTexCoord;\n"
1552 "uniform myhalf3 DeferredMod_Diffuse;\n"
1553 "uniform myhalf3 DeferredMod_Specular;\n"
1554 "#endif\n"
1555 "uniform myhalf3 Color_Ambient;\n"
1556 "uniform myhalf3 Color_Diffuse;\n"
1557 "uniform myhalf3 Color_Specular;\n"
1558 "uniform myhalf SpecularPower;\n"
1559 "#ifdef USEGLOW\n"
1560 "uniform myhalf3 Color_Glow;\n"
1561 "#endif\n"
1562 "uniform myhalf Alpha;\n"
1563 "#ifdef USEREFLECTION\n"
1564 "uniform vec4 DistortScaleRefractReflect;\n"
1565 "uniform vec4 ScreenScaleRefractReflect;\n"
1566 "uniform vec4 ScreenCenterRefractReflect;\n"
1567 "uniform myhalf4 ReflectColor;\n"
1568 "#endif\n"
1569 "#ifdef USEREFLECTCUBE\n"
1570 "uniform mat4 ModelToReflectCube;\n"
1571 "uniform sampler2D Texture_ReflectMask;\n"
1572 "uniform samplerCube Texture_ReflectCube;\n"
1573 "#endif\n"
1574 "#ifdef MODE_LIGHTDIRECTION\n"
1575 "uniform myhalf3 LightColor;\n"
1576 "#endif\n"
1577 "#ifdef MODE_LIGHTSOURCE\n"
1578 "uniform myhalf3 LightColor;\n"
1579 "#endif\n"
1580 "void main(void)\n"
1581 "{\n"
1582 "#ifdef USEOFFSETMAPPING\n"
1583 "       // apply offsetmapping\n"
1584 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1585 "#define TexCoord TexCoordOffset\n"
1586 "#endif\n"
1587 "\n"
1588 "       // combine the diffuse textures (base, pants, shirt)\n"
1589 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1590 "#ifdef USEALPHAKILL\n"
1591 "       if (color.a < 0.5)\n"
1592 "               discard;\n"
1593 "#endif\n"
1594 "       color.a *= Alpha;\n"
1595 "#ifdef USECOLORMAPPING\n"
1596 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1597 "#endif\n"
1598 "#ifdef USEVERTEXTEXTUREBLEND\n"
1599 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1600 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1601 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1602 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1603 "       color.a = 1.0;\n"
1604 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1605 "#endif\n"
1606 "\n"
1607 "       // get the surface normal\n"
1608 "#ifdef USEVERTEXTEXTUREBLEND\n"
1609 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1610 "#else\n"
1611 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1612 "#endif\n"
1613 "\n"
1614 "       // get the material colors\n"
1615 "       myhalf3 diffusetex = color.rgb;\n"
1616 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1617 "# ifdef USEVERTEXTEXTUREBLEND\n"
1618 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1619 "# else\n"
1620 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1621 "# endif\n"
1622 "#endif\n"
1623 "\n"
1624 "#ifdef USEREFLECTCUBE\n"
1625 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1626 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1627 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1628 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1629 "#endif\n"
1630 "\n"
1631 "\n"
1632 "\n"
1633 "\n"
1634 "#ifdef MODE_LIGHTSOURCE\n"
1635 "       // light source\n"
1636 "#ifdef USEDIFFUSE\n"
1637 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1638 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1639 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1640 "#ifdef USESPECULAR\n"
1641 "#ifdef USEEXACTSPECULARMATH\n"
1642 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1643 "#else\n"
1644 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1645 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1646 "#endif\n"
1647 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1648 "#endif\n"
1649 "#else\n"
1650 "       color.rgb = diffusetex * Color_Ambient;\n"
1651 "#endif\n"
1652 "       color.rgb *= LightColor;\n"
1653 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1654 "#if defined(USESHADOWMAP2D)\n"
1655 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1656 "#endif\n"
1657 "# ifdef USECUBEFILTER\n"
1658 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1659 "# endif\n"
1660 "#endif // MODE_LIGHTSOURCE\n"
1661 "\n"
1662 "\n"
1663 "\n"
1664 "\n"
1665 "#ifdef MODE_LIGHTDIRECTION\n"
1666 "#define SHADING\n"
1667 "#ifdef USEDIFFUSE\n"
1668 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1669 "#endif\n"
1670 "#define lightcolor LightColor\n"
1671 "#endif // MODE_LIGHTDIRECTION\n"
1672 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1673 "#define SHADING\n"
1674 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1675 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1676 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1677 "       // convert modelspace light vector to tangentspace\n"
1678 "       myhalf3 lightnormal;\n"
1679 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1680 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1681 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1682 "       lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1683 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1684 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1685 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1686 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1687 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1688 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1689 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1690 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1691 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1692 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1693 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1694 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1695 "#define SHADING\n"
1696 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1697 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1698 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1699 "#endif\n"
1700 "\n"
1701 "\n"
1702 "\n"
1703 "\n"
1704 "#ifdef MODE_FAKELIGHT\n"
1705 "#define SHADING\n"
1706 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1707 "myhalf3 lightcolor = myhalf3(1.0);\n"
1708 "#endif // MODE_FAKELIGHT\n"
1709 "\n"
1710 "\n"
1711 "\n"
1712 "\n"
1713 "#ifdef MODE_LIGHTMAP\n"
1714 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1715 "#endif // MODE_LIGHTMAP\n"
1716 "#ifdef MODE_VERTEXCOLOR\n"
1717 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1718 "#endif // MODE_VERTEXCOLOR\n"
1719 "#ifdef MODE_FLATCOLOR\n"
1720 "       color.rgb = diffusetex * Color_Ambient;\n"
1721 "#endif // MODE_FLATCOLOR\n"
1722 "\n"
1723 "\n"
1724 "\n"
1725 "\n"
1726 "#ifdef SHADING\n"
1727 "# ifdef USEDIFFUSE\n"
1728 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1729 "#  ifdef USESPECULAR\n"
1730 "#   ifdef USEEXACTSPECULARMATH\n"
1731 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1732 "#   else\n"
1733 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1734 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1735 "#   endif\n"
1736 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1737 "#  else\n"
1738 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1739 "#  endif\n"
1740 "# else\n"
1741 "       color.rgb = diffusetex * Color_Ambient;\n"
1742 "# endif\n"
1743 "#endif\n"
1744 "\n"
1745 "#ifdef USESHADOWMAPORTHO\n"
1746 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1747 "#endif\n"
1748 "\n"
1749 "#ifdef USEDEFERREDLIGHTMAP\n"
1750 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1751 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1752 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1753 "#endif\n"
1754 "\n"
1755 "#ifdef USEGLOW\n"
1756 "#ifdef USEVERTEXTEXTUREBLEND\n"
1757 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1758 "#else\n"
1759 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1760 "#endif\n"
1761 "#endif\n"
1762 "\n"
1763 "#ifdef USEFOG\n"
1764 "       color.rgb = FogVertex(color.rgb);\n"
1765 "#endif\n"
1766 "\n"
1767 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1768 "#ifdef USEREFLECTION\n"
1769 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1770 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1771 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1772 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1773 "       // FIXME temporary hack to detect the case that the reflection\n"
1774 "       // gets blackened at edges due to leaving the area that contains actual\n"
1775 "       // content.\n"
1776 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1777 "       // 'appening.\n"
1778 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1779 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1780 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1781 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1782 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1783 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1784 "#endif\n"
1785 "\n"
1786 "       gl_FragColor = vec4(color);\n"
1787 "}\n"
1788 "#endif // FRAGMENT_SHADER\n"
1789 "\n"
1790 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1791 "#endif // !MODE_DEFERREDGEOMETRY\n"
1792 "#endif // !MODE_WATER\n"
1793 "#endif // !MODE_REFRACTION\n"
1794 "#endif // !MODE_BLOOMBLUR\n"
1795 "#endif // !MODE_GENERIC\n"
1796 "#endif // !MODE_POSTPROCESS\n"
1797 "#endif // !MODE_SHOWDEPTH\n"
1798 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1799 ;
1800
1801 /*
1802 =========================================================================================================================================================
1803
1804
1805
1806 =========================================================================================================================================================
1807
1808
1809
1810 =========================================================================================================================================================
1811
1812
1813
1814 =========================================================================================================================================================
1815
1816
1817
1818 =========================================================================================================================================================
1819
1820
1821
1822 =========================================================================================================================================================
1823
1824
1825
1826 =========================================================================================================================================================
1827 */
1828
1829 const char *builtincgshaderstring =
1830 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1831 "// written by Forest 'LordHavoc' Hale\n"
1832 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1833 "\n"
1834 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1835 "#if defined(USEREFLECTION)\n"
1836 "#undef USESHADOWMAPORTHO\n"
1837 "#endif\n"
1838 "\n"
1839 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1840 "# define USEFOG\n"
1841 "#endif\n"
1842 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1843 "#define USELIGHTMAP\n"
1844 "#endif\n"
1845 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1846 "#define USEEYEVECTOR\n"
1847 "#endif\n"
1848 "\n"
1849 "#ifdef FRAGMENT_SHADER\n"
1850 "#ifdef HLSL\n"
1851 "//#undef USESHADOWMAPPCF\n"
1852 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1853 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1854 "#else\n"
1855 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1856 "#endif\n"
1857 "#endif\n"
1858 "\n"
1859 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1860 "#ifdef VERTEX_SHADER\n"
1861 "void main\n"
1862 "(\n"
1863 "float4 gl_Vertex : POSITION,\n"
1864 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1865 "out float4 gl_Position : POSITION,\n"
1866 "out float Depth : TEXCOORD0\n"
1867 ")\n"
1868 "{\n"
1869 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1870 "       Depth = gl_Position.z;\n"
1871 "}\n"
1872 "#endif\n"
1873 "\n"
1874 "#ifdef FRAGMENT_SHADER\n"
1875 "void main\n"
1876 "(\n"
1877 "float Depth : TEXCOORD0,\n"
1878 "out float4 gl_FragColor : COLOR\n"
1879 ")\n"
1880 "{\n"
1881 "//     float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1882 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1883 "       temp.yz -= floor(temp.yz);\n"
1884 "       gl_FragColor = temp;\n"
1885 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1886 "}\n"
1887 "#endif\n"
1888 "#else // !MODE_DEPTH_ORSHADOW\n"
1889 "\n"
1890 "\n"
1891 "\n"
1892 "\n"
1893 "#ifdef MODE_SHOWDEPTH\n"
1894 "#ifdef VERTEX_SHADER\n"
1895 "void main\n"
1896 "(\n"
1897 "float4 gl_Vertex : POSITION,\n"
1898 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1899 "out float4 gl_Position : POSITION,\n"
1900 "out float4 gl_FrontColor : COLOR0\n"
1901 ")\n"
1902 "{\n"
1903 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1904 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1905 "}\n"
1906 "#endif\n"
1907 "\n"
1908 "#ifdef FRAGMENT_SHADER\n"
1909 "void main\n"
1910 "(\n"
1911 "float4 gl_FrontColor : COLOR0,\n"
1912 "out float4 gl_FragColor : COLOR\n"
1913 ")\n"
1914 "{\n"
1915 "       gl_FragColor = gl_FrontColor;\n"
1916 "}\n"
1917 "#endif\n"
1918 "#else // !MODE_SHOWDEPTH\n"
1919 "\n"
1920 "\n"
1921 "\n"
1922 "\n"
1923 "#ifdef MODE_POSTPROCESS\n"
1924 "\n"
1925 "#ifdef VERTEX_SHADER\n"
1926 "void main\n"
1927 "(\n"
1928 "float4 gl_Vertex : POSITION,\n"
1929 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1930 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1931 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1932 "out float4 gl_Position : POSITION,\n"
1933 "out float2 TexCoord1 : TEXCOORD0,\n"
1934 "out float2 TexCoord2 : TEXCOORD1\n"
1935 ")\n"
1936 "{\n"
1937 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1938 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1939 "#ifdef USEBLOOM\n"
1940 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1941 "#endif\n"
1942 "}\n"
1943 "#endif\n"
1944 "\n"
1945 "#ifdef FRAGMENT_SHADER\n"
1946 "void main\n"
1947 "(\n"
1948 "float2 TexCoord1 : TEXCOORD0,\n"
1949 "float2 TexCoord2 : TEXCOORD1,\n"
1950 "uniform sampler Texture_First : register(s0),\n"
1951 "#ifdef USEBLOOM\n"
1952 "uniform sampler Texture_Second : register(s1),\n"
1953 "#endif\n"
1954 "#ifdef USEGAMMARAMPS\n"
1955 "uniform sampler Texture_GammaRamps : register(s2),\n"
1956 "#endif\n"
1957 "#ifdef USESATURATION\n"
1958 "uniform float Saturation : register(c30),\n"
1959 "#endif\n"
1960 "#ifdef USEVIEWTINT\n"
1961 "uniform float4 ViewTintColor : register(c41),\n"
1962 "#endif\n"
1963 "uniform float4 UserVec1 : register(c37),\n"
1964 "uniform float4 UserVec2 : register(c38),\n"
1965 "uniform float4 UserVec3 : register(c39),\n"
1966 "uniform float4 UserVec4 : register(c40),\n"
1967 "uniform float ClientTime : register(c2),\n"
1968 "uniform float2 PixelSize : register(c25),\n"
1969 "uniform float4 BloomColorSubtract : register(c43),\n"
1970 "out float4 gl_FragColor : COLOR\n"
1971 ")\n"
1972 "{\n"
1973 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1974 "#ifdef USEBLOOM\n"
1975 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1976 "#endif\n"
1977 "#ifdef USEVIEWTINT\n"
1978 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1979 "#endif\n"
1980 "\n"
1981 "#ifdef USEPOSTPROCESSING\n"
1982 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1983 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
1984 "       float sobel = 1.0;\n"
1985 "       // float2 ts = textureSize(Texture_First, 0);\n"
1986 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
1987 "       float2 px = PixelSize;\n"
1988 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1989 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
1990 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1991 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1992 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
1993 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1994 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1995 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
1996 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1997 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1998 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
1999 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2000 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2001 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2002 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2003 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2004 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2005 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2006 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2007 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2008 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2009 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2010 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2011 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2012 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2013 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2014 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2015 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2016 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2017 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2018 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2019 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2020 "#endif\n"
2021 "\n"
2022 "#ifdef USESATURATION\n"
2023 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2024 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2025 "       // 'vampire sight' effect, wheres red is compensated\n"
2026 "       #ifdef SATURATION_REDCOMPENSATE\n"
2027 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2028 "               gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2029 "               gl_FragColor.r += r;\n"
2030 "       #else\n"
2031 "               // normal desaturation\n"
2032 "               //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2033 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2034 "       #endif\n"
2035 "#endif\n"
2036 "\n"
2037 "#ifdef USEGAMMARAMPS\n"
2038 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2039 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2040 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2041 "#endif\n"
2042 "}\n"
2043 "#endif\n"
2044 "#else // !MODE_POSTPROCESS\n"
2045 "\n"
2046 "\n"
2047 "\n"
2048 "\n"
2049 "#ifdef MODE_GENERIC\n"
2050 "#ifdef VERTEX_SHADER\n"
2051 "void main\n"
2052 "(\n"
2053 "float4 gl_Vertex : POSITION,\n"
2054 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2055 "float4 gl_Color : COLOR0,\n"
2056 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2057 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2058 "out float4 gl_Position : POSITION,\n"
2059 "#ifdef USEDIFFUSE\n"
2060 "out float2 TexCoord1 : TEXCOORD0,\n"
2061 "#endif\n"
2062 "#ifdef USESPECULAR\n"
2063 "out float2 TexCoord2 : TEXCOORD1,\n"
2064 "#endif\n"
2065 "out float4 gl_FrontColor : COLOR\n"
2066 ")\n"
2067 "{\n"
2068 "#ifdef HLSL\n"
2069 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2070 "#else\n"
2071 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2072 "#endif\n"
2073 "#ifdef USEDIFFUSE\n"
2074 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2075 "#endif\n"
2076 "#ifdef USESPECULAR\n"
2077 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2078 "#endif\n"
2079 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2080 "}\n"
2081 "#endif\n"
2082 "\n"
2083 "#ifdef FRAGMENT_SHADER\n"
2084 "\n"
2085 "void main\n"
2086 "(\n"
2087 "float4 gl_FrontColor : COLOR0,\n"
2088 "float2 TexCoord1 : TEXCOORD0,\n"
2089 "float2 TexCoord2 : TEXCOORD1,\n"
2090 "#ifdef USEDIFFUSE\n"
2091 "uniform sampler Texture_First : register(s0),\n"
2092 "#endif\n"
2093 "#ifdef USESPECULAR\n"
2094 "uniform sampler Texture_Second : register(s1),\n"
2095 "#endif\n"
2096 "out float4 gl_FragColor : COLOR\n"
2097 ")\n"
2098 "{\n"
2099 "#ifdef USEVIEWTINT\n"
2100 "       gl_FragColor = gl_FrontColor;\n"
2101 "#else\n"
2102 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2103 "#endif\n"
2104 "#ifdef USEDIFFUSE\n"
2105 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2106 "#endif\n"
2107 "\n"
2108 "#ifdef USESPECULAR\n"
2109 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2110 "# ifdef USECOLORMAPPING\n"
2111 "       gl_FragColor *= tex2;\n"
2112 "# endif\n"
2113 "# ifdef USEGLOW\n"
2114 "       gl_FragColor += tex2;\n"
2115 "# endif\n"
2116 "# ifdef USEVERTEXTEXTUREBLEND\n"
2117 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2118 "# endif\n"
2119 "#endif\n"
2120 "}\n"
2121 "#endif\n"
2122 "#else // !MODE_GENERIC\n"
2123 "\n"
2124 "\n"
2125 "\n"
2126 "\n"
2127 "#ifdef MODE_BLOOMBLUR\n"
2128 "#ifdef VERTEX_SHADER\n"
2129 "void main\n"
2130 "(\n"
2131 "float4 gl_Vertex : POSITION,\n"
2132 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2133 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2134 "out float4 gl_Position : POSITION,\n"
2135 "out float2 TexCoord : TEXCOORD0\n"
2136 ")\n"
2137 "{\n"
2138 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2139 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2140 "}\n"
2141 "#endif\n"
2142 "\n"
2143 "#ifdef FRAGMENT_SHADER\n"
2144 "\n"
2145 "void main\n"
2146 "(\n"
2147 "float2 TexCoord : TEXCOORD0,\n"
2148 "uniform sampler Texture_First : register(s0),\n"
2149 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2150 "out float4 gl_FragColor : COLOR\n"
2151 ")\n"
2152 "{\n"
2153 "       int i;\n"
2154 "       float2 tc = TexCoord;\n"
2155 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2156 "       tc += BloomBlur_Parameters.xy;\n"
2157 "       for (i = 1;i < SAMPLES;i++)\n"
2158 "       {\n"
2159 "               color += tex2D(Texture_First, tc).rgb;\n"
2160 "               tc += BloomBlur_Parameters.xy;\n"
2161 "       }\n"
2162 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2163 "}\n"
2164 "#endif\n"
2165 "#else // !MODE_BLOOMBLUR\n"
2166 "#ifdef MODE_REFRACTION\n"
2167 "#ifdef VERTEX_SHADER\n"
2168 "void main\n"
2169 "(\n"
2170 "float4 gl_Vertex : POSITION,\n"
2171 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2172 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2173 "uniform float4x4 TexMatrix : register(c0),\n"
2174 "uniform float3 EyePosition : register(c24),\n"
2175 "out float4 gl_Position : POSITION,\n"
2176 "out float2 TexCoord : TEXCOORD0,\n"
2177 "out float3 EyeVector : TEXCOORD1,\n"
2178 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2179 ")\n"
2180 "{\n"
2181 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2182 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2183 "       ModelViewProjectionPosition = gl_Position;\n"
2184 "}\n"
2185 "#endif\n"
2186 "\n"
2187 "#ifdef FRAGMENT_SHADER\n"
2188 "void main\n"
2189 "(\n"
2190 "float2 TexCoord : TEXCOORD0,\n"
2191 "float3 EyeVector : TEXCOORD1,\n"
2192 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2193 "uniform sampler Texture_Normal : register(s0),\n"
2194 "uniform sampler Texture_Refraction : register(s3),\n"
2195 "uniform sampler Texture_Reflection : register(s7),\n"
2196 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2197 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2198 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2199 "uniform float4 RefractColor : register(c29),\n"
2200 "out float4 gl_FragColor : COLOR\n"
2201 ")\n"
2202 "{\n"
2203 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2204 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2205 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2206 "       float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2207 "       // FIXME temporary hack to detect the case that the reflection\n"
2208 "       // gets blackened at edges due to leaving the area that contains actual\n"
2209 "       // content.\n"
2210 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2211 "       // 'appening.\n"
2212 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2213 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2214 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2215 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2216 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2217 "       gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2218 "}\n"
2219 "#endif\n"
2220 "#else // !MODE_REFRACTION\n"
2221 "\n"
2222 "\n"
2223 "\n"
2224 "\n"
2225 "#ifdef MODE_WATER\n"
2226 "#ifdef VERTEX_SHADER\n"
2227 "\n"
2228 "void main\n"
2229 "(\n"
2230 "float4 gl_Vertex : POSITION,\n"
2231 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2232 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2233 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2234 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2235 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2236 "uniform float4x4 TexMatrix : register(c0),\n"
2237 "uniform float3 EyePosition : register(c24),\n"
2238 "out float4 gl_Position : POSITION,\n"
2239 "out float2 TexCoord : TEXCOORD0,\n"
2240 "out float3 EyeVector : TEXCOORD1,\n"
2241 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2242 ")\n"
2243 "{\n"
2244 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2245 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2246 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2247 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2248 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2249 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2250 "       ModelViewProjectionPosition = gl_Position;\n"
2251 "}\n"
2252 "#endif\n"
2253 "\n"
2254 "#ifdef FRAGMENT_SHADER\n"
2255 "void main\n"
2256 "(\n"
2257 "float2 TexCoord : TEXCOORD0,\n"
2258 "float3 EyeVector : TEXCOORD1,\n"
2259 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2260 "uniform sampler Texture_Normal : register(s0),\n"
2261 "uniform sampler Texture_Refraction : register(s3),\n"
2262 "uniform sampler Texture_Reflection : register(s7),\n"
2263 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2264 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2265 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2266 "uniform float4 RefractColor : register(c29),\n"
2267 "uniform float4 ReflectColor : register(c26),\n"
2268 "uniform float ReflectFactor : register(c27),\n"
2269 "uniform float ReflectOffset : register(c28),\n"
2270 "out float4 gl_FragColor : COLOR\n"
2271 ")\n"
2272 "{\n"
2273 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2274 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2275 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2276 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2277 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2278 "       // FIXME temporary hack to detect the case that the reflection\n"
2279 "       // gets blackened at edges due to leaving the area that contains actual\n"
2280 "       // content.\n"
2281 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2282 "       // 'appening.\n"
2283 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2284 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2285 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2286 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2287 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2288 "       f  = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2289 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2290 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2291 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2292 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2293 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2294 "       gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2295 "}\n"
2296 "#endif\n"
2297 "#else // !MODE_WATER\n"
2298 "\n"
2299 "\n"
2300 "\n"
2301 "\n"
2302 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
2303 "\n"
2304 "// fragment shader specific:\n"
2305 "#ifdef FRAGMENT_SHADER\n"
2306 "\n"
2307 "#ifdef USEFOG\n"
2308 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2309 "{\n"
2310 "       float fogfrac;\n"
2311 "#ifdef USEFOGHEIGHTTEXTURE\n"
2312 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2313 "       fogfrac = fogheightpixel.a;\n"
2314 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2315 "#else\n"
2316 "# ifdef USEFOGOUTSIDE\n"
2317 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2318 "# else\n"
2319 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2320 "# endif\n"
2321 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2322 "#endif\n"
2323 "}\n"
2324 "#endif\n"
2325 "\n"
2326 "#ifdef USEOFFSETMAPPING\n"
2327 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2328 "{\n"
2329 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2330 "       // 14 sample relief mapping: linear search and then binary search\n"
2331 "       // this basically steps forward a small amount repeatedly until it finds\n"
2332 "       // itself inside solid, then jitters forward and back using decreasing\n"
2333 "       // amounts to find the impact\n"
2334 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2335 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2336 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2337 "       float3 RT = float3(TexCoord, 1);\n"
2338 "       OffsetVector *= 0.1;\n"
2339 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2340 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2341 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2342 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2343 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2344 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2345 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2346 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2347 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2348 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2349 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2350 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2351 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2352 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2353 "       return RT.xy;\n"
2354 "#else\n"
2355 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2356 "       // this basically moves forward the full distance, and then backs up based\n"
2357 "       // on height of samples\n"
2358 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2359 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2360 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2361 "       TexCoord += OffsetVector;\n"
2362 "       OffsetVector *= 0.333;\n"
2363 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2364 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2365 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2366 "       return TexCoord;\n"
2367 "#endif\n"
2368 "}\n"
2369 "#endif // USEOFFSETMAPPING\n"
2370 "\n"
2371 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2372 "#if defined(USESHADOWMAP2D)\n"
2373 "# ifdef USESHADOWMAPORTHO\n"
2374 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2375 "# else\n"
2376 "#  ifdef USESHADOWMAPVSDCT\n"
2377 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2378 "{\n"
2379 "       float3 adir = abs(dir);\n"
2380 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2381 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2382 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2383 "}\n"
2384 "#  else\n"
2385 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2386 "{\n"
2387 "       float3 adir = abs(dir);\n"
2388 "       float ma = adir.z;\n"
2389 "       float4 proj = float4(dir, 2.5);\n"
2390 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2391 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2392 "#ifdef HLSL\n"
2393 "       return float3(proj.xy * ShadowMap_Parameters.x / ma + float2(0.5,0.5) + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, ma + 64 * ShadowMap_Parameters.w);\n"
2394 "#else\n"
2395 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2396 "       return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2397 "#endif\n"
2398 "}\n"
2399 "#  endif\n"
2400 "# endif\n"
2401 "#endif // defined(USESHADOWMAP2D)\n"
2402 "\n"
2403 "# ifdef USESHADOWMAP2D\n"
2404 "#ifdef USESHADOWMAPVSDCT\n"
2405 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2406 "#else\n"
2407 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2408 "#endif\n"
2409 "{\n"
2410 "#ifdef USESHADOWMAPVSDCT\n"
2411 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2412 "#else\n"
2413 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2414 "#endif\n"
2415 "       float f;\n"
2416 "\n"
2417 "#  ifdef USESHADOWSAMPLER\n"
2418 "#    ifdef USESHADOWMAPPCF\n"
2419 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2420 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2421 "       f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2422 "#    else\n"
2423 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2424 "#    endif\n"
2425 "#  else\n"
2426 "#    ifdef USESHADOWMAPPCF\n"
2427 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2428 "#      ifdef GL_ARB_texture_gather\n"
2429 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2430 "#      else\n"
2431 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2432 "#      endif\n"
2433 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2434 "#      if USESHADOWMAPPCF > 1\n"
2435 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2436 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2437 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2438 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2439 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2440 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2441 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2442 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2443 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2444 "       float4 locols = float4(group1.ab, group3.ab);\n"
2445 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2446 "       locols.yz += group2.ab;\n"
2447 "       hicols.yz += group8.rg;\n"
2448 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2449 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2450 "                               lerp(locols, hicols, offset.y);\n"
2451 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2452 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2453 "       f = dot(cols, float4(1.0/25.0));\n"
2454 "#      else\n"
2455 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2456 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2457 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2458 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2459 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2460 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2461 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2462 "#      endif\n"
2463 "#     else\n"
2464 "#      ifdef GL_EXT_gpu_shader4\n"
2465 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2466 "#      else\n"
2467 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2468 "#      endif\n"
2469 "#      if USESHADOWMAPPCF > 1\n"
2470 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2471 "       center *= ShadowMap_TextureScale;\n"
2472 "       float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2473 "       float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2474 "       float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2475 "       float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2476 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2477 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2478 "#      else\n"
2479 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2480 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2481 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2482 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2483 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2484 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2485 "#      endif\n"
2486 "#     endif\n"
2487 "#    else\n"
2488 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2489 "#    endif\n"
2490 "#  endif\n"
2491 "#  ifdef USESHADOWMAPORTHO\n"
2492 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2493 "#  else\n"
2494 "       return f;\n"
2495 "#  endif\n"
2496 "}\n"
2497 "# endif\n"
2498 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2499 "#endif // FRAGMENT_SHADER\n"
2500 "\n"
2501 "\n"
2502 "\n"
2503 "\n"
2504 "#ifdef MODE_DEFERREDGEOMETRY\n"
2505 "#ifdef VERTEX_SHADER\n"
2506 "void main\n"
2507 "(\n"
2508 "float4 gl_Vertex : POSITION,\n"
2509 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2510 "#ifdef USEVERTEXTEXTUREBLEND\n"
2511 "float4 gl_Color : COLOR0,\n"
2512 "#endif\n"
2513 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2514 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2515 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2516 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2517 "uniform float4x4 TexMatrix : register(c0),\n"
2518 "#ifdef USEVERTEXTEXTUREBLEND\n"
2519 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2520 "#endif\n"
2521 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2522 "#ifdef USEOFFSETMAPPING\n"
2523 "uniform float3 EyePosition : register(c24),\n"
2524 "#endif\n"
2525 "out float4 gl_Position : POSITION,\n"
2526 "#ifdef USEVERTEXTEXTUREBLEND\n"
2527 "out float4 gl_FrontColor : COLOR,\n"
2528 "#endif\n"
2529 "out float4 TexCoordBoth : TEXCOORD0,\n"
2530 "#ifdef USEOFFSETMAPPING\n"
2531 "out float3 EyeVector : TEXCOORD2,\n"
2532 "#endif\n"
2533 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2534 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2535 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2536 ")\n"
2537 "{\n"
2538 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2539 "#ifdef USEVERTEXTEXTUREBLEND\n"
2540 "#ifdef HLSL\n"
2541 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2542 "#else\n"
2543 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2544 "#endif\n"
2545 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2546 "#endif\n"
2547 "\n"
2548 "       // transform unnormalized eye direction into tangent space\n"
2549 "#ifdef USEOFFSETMAPPING\n"
2550 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2551 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2552 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2553 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2554 "#endif\n"
2555 "\n"
2556 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2557 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2558 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2559 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2560 "       VectorR.w = gl_Position.z;\n"
2561 "}\n"
2562 "#endif // VERTEX_SHADER\n"
2563 "\n"
2564 "#ifdef FRAGMENT_SHADER\n"
2565 "void main\n"
2566 "(\n"
2567 "float4 TexCoordBoth : TEXCOORD0,\n"
2568 "float3 EyeVector : TEXCOORD2,\n"
2569 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2570 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2571 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2572 "uniform sampler Texture_Normal : register(s0),\n"
2573 "#ifdef USEALPHAKILL\n"
2574 "uniform sampler Texture_Color : register(s1),\n"
2575 "#endif\n"
2576 "uniform sampler Texture_Gloss : register(s2),\n"
2577 "#ifdef USEVERTEXTEXTUREBLEND\n"
2578 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2579 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2580 "#endif\n"
2581 "#ifdef USEOFFSETMAPPING\n"
2582 "uniform float OffsetMapping_Scale : register(c24),\n"
2583 "#endif\n"
2584 "uniform half SpecularPower : register(c36),\n"
2585 "#ifdef HLSL\n"
2586 "out float4 gl_FragData0 : COLOR0,\n"
2587 "out float4 gl_FragData1 : COLOR1\n"
2588 "#else\n"
2589 "out float4 gl_FragColor : COLOR\n"
2590 "#endif\n"
2591 ")\n"
2592 "{\n"
2593 "       float2 TexCoord = TexCoordBoth.xy;\n"
2594 "#ifdef USEOFFSETMAPPING\n"
2595 "       // apply offsetmapping\n"
2596 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2597 "#define TexCoord TexCoordOffset\n"
2598 "#endif\n"
2599 "\n"
2600 "#ifdef USEALPHAKILL\n"
2601 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2602 "               discard;\n"
2603 "#endif\n"
2604 "\n"
2605 "#ifdef USEVERTEXTEXTUREBLEND\n"
2606 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2607 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2608 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2609 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2610 "#endif\n"
2611 "\n"
2612 "#ifdef USEVERTEXTEXTUREBLEND\n"
2613 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2614 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2615 "#else\n"
2616 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2617 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2618 "#endif\n"
2619 "\n"
2620 "#ifdef HLSL\n"
2621 "       gl_FragData0 = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR.xyz) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2622 "       float Depth = VectorR.w / 256.0;\n"
2623 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2624 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2625 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2626 "       gl_FragData1 = depthcolor;\n"
2627 "#else\n"
2628 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2629 "#endif\n"
2630 "}\n"
2631 "#endif // FRAGMENT_SHADER\n"
2632 "#else // !MODE_DEFERREDGEOMETRY\n"
2633 "\n"
2634 "\n"
2635 "\n"
2636 "\n"
2637 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2638 "#ifdef VERTEX_SHADER\n"
2639 "void main\n"
2640 "(\n"
2641 "float4 gl_Vertex : POSITION,\n"
2642 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2643 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2644 "out float4 gl_Position : POSITION,\n"
2645 "out float4 ModelViewPosition : TEXCOORD0\n"
2646 ")\n"
2647 "{\n"
2648 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2649 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2650 "}\n"
2651 "#endif // VERTEX_SHADER\n"
2652 "\n"
2653 "#ifdef FRAGMENT_SHADER\n"
2654 "void main\n"
2655 "(\n"
2656 "#ifdef HLSL\n"
2657 "float2 Pixel : VPOS,\n"
2658 "#else\n"
2659 "float2 Pixel : WPOS,\n"
2660 "#endif\n"
2661 "float4 ModelViewPosition : TEXCOORD0,\n"
2662 "uniform float4x4 ViewToLight : register(c44),\n"
2663 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2664 "uniform float3 LightPosition : register(c23),\n"
2665 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2666 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2667 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2668 "#ifdef USESPECULAR\n"
2669 "uniform half3 DeferredColor_Specular : register(c11),\n"
2670 "uniform half SpecularPower : register(c36),\n"
2671 "#endif\n"
2672 "uniform sampler Texture_Attenuation : register(s9),\n"
2673 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2674 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2675 "\n"
2676 "#ifdef USECUBEFILTER\n"
2677 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2678 "#endif\n"
2679 "\n"
2680 "#ifdef USESHADOWMAP2D\n"
2681 "# ifdef USESHADOWSAMPLER\n"
2682 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2683 "# else\n"
2684 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2685 "# endif\n"
2686 "#endif\n"
2687 "\n"
2688 "#ifdef USESHADOWMAPVSDCT\n"
2689 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2690 "#endif\n"
2691 "\n"
2692 "#if defined(USESHADOWMAP2D)\n"
2693 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2694 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2695 "#endif\n"
2696 "\n"
2697 "out float4 gl_FragData0 : COLOR0,\n"
2698 "out float4 gl_FragData1 : COLOR1\n"
2699 ")\n"
2700 "{\n"
2701 "       // calculate viewspace pixel position\n"
2702 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2703 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2704 "       float3 position;\n"
2705 "#ifdef HLSL\n"
2706 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2707 "#else\n"
2708 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2709 "#endif\n"
2710 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2711 "       // decode viewspace pixel normal\n"
2712 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2713 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2714 "       // surfacenormal = pixel normal in viewspace\n"
2715 "       // LightVector = pixel to light in viewspace\n"
2716 "       // CubeVector = position in lightspace\n"
2717 "       // eyevector = pixel to view in viewspace\n"
2718 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2719 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2720 "#ifdef USEDIFFUSE\n"
2721 "       // calculate diffuse shading\n"
2722 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2723 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2724 "#endif\n"
2725 "#ifdef USESPECULAR\n"
2726 "       // calculate directional shading\n"
2727 "       float3 eyevector = position * -1.0;\n"
2728 "#  ifdef USEEXACTSPECULARMATH\n"
2729 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2730 "#  else\n"
2731 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2732 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2733 "#  endif\n"
2734 "#endif\n"
2735 "\n"
2736 "#if defined(USESHADOWMAP2D)\n"
2737 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2738 "#ifdef USESHADOWMAPVSDCT\n"
2739 ", Texture_CubeProjection\n"
2740 "#endif\n"
2741 "       ));\n"
2742 "#endif\n"
2743 "\n"
2744 "#ifdef USEDIFFUSE\n"
2745 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2746 "#else\n"
2747 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2748 "#endif\n"
2749 "#ifdef USESPECULAR\n"
2750 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2751 "#else\n"
2752 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2753 "#endif\n"
2754 "\n"
2755 "# ifdef USECUBEFILTER\n"
2756 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2757 "       gl_FragData0.rgb *= cubecolor;\n"
2758 "       gl_FragData1.rgb *= cubecolor;\n"
2759 "# endif\n"
2760 "}\n"
2761 "#endif // FRAGMENT_SHADER\n"
2762 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2763 "\n"
2764 "\n"
2765 "\n"
2766 "\n"
2767 "#ifdef VERTEX_SHADER\n"
2768 "void main\n"
2769 "(\n"
2770 "float4 gl_Vertex : POSITION,\n"
2771 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2772 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2773 "float4 gl_Color : COLOR0,\n"
2774 "#endif\n"
2775 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2776 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2777 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2778 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2779 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2780 "\n"
2781 "uniform float3 EyePosition : register(c24),\n"
2782 "uniform float4x4 TexMatrix : register(c0),\n"
2783 "#ifdef USEVERTEXTEXTUREBLEND\n"
2784 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2785 "#endif\n"
2786 "#ifdef MODE_LIGHTSOURCE\n"
2787 "uniform float4x4 ModelToLight : register(c20),\n"
2788 "#endif\n"
2789 "#ifdef MODE_LIGHTSOURCE\n"
2790 "uniform float3 LightPosition : register(c27),\n"
2791 "#endif\n"
2792 "#ifdef MODE_LIGHTDIRECTION\n"
2793 "uniform float3 LightDir : register(c26),\n"
2794 "#endif\n"
2795 "uniform float4 FogPlane : register(c25),\n"
2796 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2797 "uniform float3 LightPosition : register(c27),\n"
2798 "#endif\n"
2799 "#ifdef USESHADOWMAPORTHO\n"
2800 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2801 "#endif\n"
2802 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2803 "out float4 gl_FrontColor : COLOR,\n"
2804 "#endif\n"
2805 "out float4 TexCoordBoth : TEXCOORD0,\n"
2806 "#ifdef USELIGHTMAP\n"
2807 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2808 "#endif\n"
2809 "#ifdef USEEYEVECTOR\n"
2810 "out float3 EyeVector : TEXCOORD2,\n"
2811 "#endif\n"
2812 "#ifdef USEREFLECTION\n"
2813 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2814 "#endif\n"
2815 "#ifdef USEFOG\n"
2816 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2817 "#endif\n"
2818 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2819 "out float3 LightVector : TEXCOORD1,\n"
2820 "#endif\n"
2821 "#ifdef MODE_LIGHTSOURCE\n"
2822 "out float3 CubeVector : TEXCOORD3,\n"
2823 "#endif\n"
2824 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2825 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2826 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2827 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2828 "#endif\n"
2829 "#ifdef USESHADOWMAPORTHO\n"
2830 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2831 "#endif\n"
2832 "out float4 gl_Position : POSITION\n"
2833 ")\n"
2834 "{\n"
2835 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2836 "#ifdef HLSL\n"
2837 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2838 "#else\n"
2839 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2840 "#endif\n"
2841 "#endif\n"
2842 "       // copy the surface texcoord\n"
2843 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2844 "#ifdef USEVERTEXTEXTUREBLEND\n"
2845 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2846 "#endif\n"
2847 "#ifdef USELIGHTMAP\n"
2848 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2849 "#endif\n"
2850 "\n"
2851 "#ifdef MODE_LIGHTSOURCE\n"
2852 "       // transform vertex position into light attenuation/cubemap space\n"
2853 "       // (-1 to +1 across the light box)\n"
2854 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2855 "\n"
2856 "# ifdef USEDIFFUSE\n"
2857 "       // transform unnormalized light direction into tangent space\n"
2858 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2859 "       //  normalize it per pixel)\n"
2860 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2861 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2862 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2863 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2864 "# endif\n"
2865 "#endif\n"
2866 "\n"
2867 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2868 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2869 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2870 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2871 "#endif\n"
2872 "\n"
2873 "       // transform unnormalized eye direction into tangent space\n"
2874 "#ifdef USEEYEVECTOR\n"
2875 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2876 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2877 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2878 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2879 "#endif\n"
2880 "\n"
2881 "#ifdef USEFOG\n"
2882 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2883 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2884 "#endif\n"
2885 "\n"
2886 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2887 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2888 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2889 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2890 "#endif\n"
2891 "\n"
2892 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2893 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2894 "\n"
2895 "#ifdef USESHADOWMAPORTHO\n"
2896 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2897 "#endif\n"
2898 "\n"
2899 "#ifdef USEREFLECTION\n"
2900 "       ModelViewProjectionPosition = gl_Position;\n"
2901 "#endif\n"
2902 "}\n"
2903 "#endif // VERTEX_SHADER\n"
2904 "\n"
2905 "\n"
2906 "\n"
2907 "\n"
2908 "#ifdef FRAGMENT_SHADER\n"
2909 "void main\n"
2910 "(\n"
2911 "#ifdef USEDEFERREDLIGHTMAP\n"
2912 "#ifdef HLSL\n"
2913 "float2 Pixel : VPOS,\n"
2914 "#else\n"
2915 "float2 Pixel : WPOS,\n"
2916 "#endif\n"
2917 "#endif\n"
2918 "float4 gl_FrontColor : COLOR,\n"
2919 "float4 TexCoordBoth : TEXCOORD0,\n"
2920 "#ifdef USELIGHTMAP\n"
2921 "float2 TexCoordLightmap : TEXCOORD1,\n"
2922 "#endif\n"
2923 "#ifdef USEEYEVECTOR\n"
2924 "float3 EyeVector : TEXCOORD2,\n"
2925 "#endif\n"
2926 "#ifdef USEREFLECTION\n"
2927 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2928 "#endif\n"
2929 "#ifdef USEFOG\n"
2930 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2931 "#endif\n"
2932 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2933 "float3 LightVector : TEXCOORD1,\n"
2934 "#endif\n"
2935 "#ifdef MODE_LIGHTSOURCE\n"
2936 "float3 CubeVector : TEXCOORD3,\n"
2937 "#endif\n"
2938 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2939 "float4 ModelViewPosition : TEXCOORD0,\n"
2940 "#endif\n"
2941 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2942 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2943 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2944 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2945 "#endif\n"
2946 "#ifdef USESHADOWMAPORTHO\n"
2947 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2948 "#endif\n"
2949 "\n"
2950 "uniform sampler Texture_Normal : register(s0),\n"
2951 "uniform sampler Texture_Color : register(s1),\n"
2952 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2953 "uniform sampler Texture_Gloss : register(s2),\n"
2954 "#endif\n"
2955 "#ifdef USEGLOW\n"
2956 "uniform sampler Texture_Glow : register(s3),\n"
2957 "#endif\n"
2958 "#ifdef USEVERTEXTEXTUREBLEND\n"
2959 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2960 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2961 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2962 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2963 "#endif\n"
2964 "#ifdef USEGLOW\n"
2965 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2966 "#endif\n"
2967 "#endif\n"
2968 "#ifdef USECOLORMAPPING\n"
2969 "uniform sampler Texture_Pants : register(s4),\n"
2970 "uniform sampler Texture_Shirt : register(s7),\n"
2971 "#endif\n"
2972 "#ifdef USEFOG\n"
2973 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2974 "uniform sampler Texture_FogMask : register(s8),\n"
2975 "#endif\n"
2976 "#ifdef USELIGHTMAP\n"
2977 "uniform sampler Texture_Lightmap : register(s9),\n"
2978 "#endif\n"
2979 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2980 "uniform sampler Texture_Deluxemap : register(s10),\n"
2981 "#endif\n"
2982 "#ifdef USEREFLECTION\n"
2983 "uniform sampler Texture_Reflection : register(s7),\n"
2984 "#endif\n"
2985 "\n"
2986 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2987 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2988 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2989 "#endif\n"
2990 "#ifdef USEDEFERREDLIGHTMAP\n"
2991 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2992 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2993 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2994 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2995 "#endif\n"
2996 "\n"
2997 "#ifdef USECOLORMAPPING\n"
2998 "uniform half3 Color_Pants : register(c7),\n"
2999 "uniform half3 Color_Shirt : register(c8),\n"
3000 "#endif\n"
3001 "#ifdef USEFOG\n"
3002 "uniform float3 FogColor : register(c16),\n"
3003 "uniform float FogRangeRecip : register(c20),\n"
3004 "uniform float FogPlaneViewDist : register(c19),\n"
3005 "uniform float FogHeightFade : register(c17),\n"
3006 "#endif\n"
3007 "\n"
3008 "#ifdef USEOFFSETMAPPING\n"
3009 "uniform float OffsetMapping_Scale : register(c24),\n"
3010 "#endif\n"
3011 "\n"
3012 "#ifdef USEDEFERREDLIGHTMAP\n"
3013 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3014 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3015 "uniform half3 DeferredMod_Specular : register(c13),\n"
3016 "#endif\n"
3017 "uniform half3 Color_Ambient : register(c3),\n"
3018 "uniform half3 Color_Diffuse : register(c4),\n"
3019 "uniform half3 Color_Specular : register(c5),\n"
3020 "uniform half SpecularPower : register(c36),\n"
3021 "#ifdef USEGLOW\n"
3022 "uniform half3 Color_Glow : register(c6),\n"
3023 "#endif\n"
3024 "uniform half Alpha : register(c0),\n"
3025 "#ifdef USEREFLECTION\n"
3026 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3027 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3028 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3029 "uniform half4 ReflectColor : register(c26),\n"
3030 "#endif\n"
3031 "#ifdef USEREFLECTCUBE\n"
3032 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3033 "uniform sampler Texture_ReflectMask : register(s5),\n"
3034 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3035 "#endif\n"
3036 "#ifdef MODE_LIGHTDIRECTION\n"
3037 "uniform half3 LightColor : register(c21),\n"
3038 "#endif\n"
3039 "#ifdef MODE_LIGHTSOURCE\n"
3040 "uniform half3 LightColor : register(c21),\n"
3041 "#endif\n"
3042 "\n"
3043 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3044 "uniform sampler Texture_Attenuation : register(s9),\n"
3045 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3046 "#endif\n"
3047 "\n"
3048 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3049 "\n"
3050 "#ifdef USESHADOWMAP2D\n"
3051 "# ifdef USESHADOWSAMPLER\n"
3052 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3053 "# else\n"
3054 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3055 "# endif\n"
3056 "#endif\n"
3057 "\n"
3058 "#ifdef USESHADOWMAPVSDCT\n"
3059 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3060 "#endif\n"
3061 "\n"
3062 "#if defined(USESHADOWMAP2D)\n"
3063 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3064 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3065 "#endif\n"
3066 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3067 "\n"
3068 "out float4 gl_FragColor : COLOR\n"
3069 ")\n"
3070 "{\n"
3071 "       float2 TexCoord = TexCoordBoth.xy;\n"
3072 "#ifdef USEVERTEXTEXTUREBLEND\n"
3073 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3074 "#endif\n"
3075 "#ifdef USEOFFSETMAPPING\n"
3076 "       // apply offsetmapping\n"
3077 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3078 "#define TexCoord TexCoordOffset\n"
3079 "#endif\n"
3080 "\n"
3081 "       // combine the diffuse textures (base, pants, shirt)\n"
3082 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3083 "#ifdef USEALPHAKILL\n"
3084 "       if (color.a < 0.5)\n"
3085 "               discard;\n"
3086 "#endif\n"
3087 "       color.a *= Alpha;\n"
3088 "#ifdef USECOLORMAPPING\n"
3089 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3090 "#endif\n"
3091 "#ifdef USEVERTEXTEXTUREBLEND\n"
3092 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3093 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3094 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3095 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3096 "       color.a = 1.0;\n"
3097 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3098 "#endif\n"
3099 "\n"
3100 "       // get the surface normal\n"
3101 "#ifdef USEVERTEXTEXTUREBLEND\n"
3102 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3103 "#else\n"
3104 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3105 "#endif\n"
3106 "\n"
3107 "       // get the material colors\n"
3108 "       half3 diffusetex = color.rgb;\n"
3109 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3110 "# ifdef USEVERTEXTEXTUREBLEND\n"
3111 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3112 "# else\n"
3113 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3114 "# endif\n"
3115 "#endif\n"
3116 "\n"
3117 "#ifdef USEREFLECTCUBE\n"
3118 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3119 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3120 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3121 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3122 "#endif\n"
3123 "\n"
3124 "\n"
3125 "\n"
3126 "\n"
3127 "#ifdef MODE_LIGHTSOURCE\n"
3128 "       // light source\n"
3129 "#ifdef USEDIFFUSE\n"
3130 "       half3 lightnormal = half3(normalize(LightVector));\n"
3131 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3132 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3133 "#ifdef USESPECULAR\n"
3134 "#ifdef USEEXACTSPECULARMATH\n"
3135 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3136 "#else\n"
3137 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3138 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3139 "#endif\n"
3140 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3141 "#endif\n"
3142 "#else\n"
3143 "       color.rgb = diffusetex * Color_Ambient;\n"
3144 "#endif\n"
3145 "       color.rgb *= LightColor;\n"
3146 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3147 "#if defined(USESHADOWMAP2D)\n"
3148 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3149 "#ifdef USESHADOWMAPVSDCT\n"
3150 ", Texture_CubeProjection\n"
3151 "#endif\n"
3152 "       ));\n"
3153 "\n"
3154 "#endif\n"
3155 "# ifdef USECUBEFILTER\n"
3156 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3157 "# endif\n"
3158 "\n"
3159 "#ifdef USESHADOWMAP2D\n"
3160 "#ifdef USESHADOWMAPVSDCT\n"
3161 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3162 "#else\n"
3163 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3164 "#endif\n"
3165 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3166 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3167 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3168 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3169 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3170 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3171 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3172 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3173 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3174 "//     color.r = half(shadowmaptc.z);\n"
3175 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3176 "//     color.r = half(shadowmaptc.z);\n"
3177 "//     color.r = 1;\n"
3178 "//     color.rgb = abs(CubeVector);\n"
3179 "#endif\n"
3180 "//     color.rgb = half3(1,1,1);\n"
3181 "#endif // MODE_LIGHTSOURCE\n"
3182 "\n"
3183 "\n"
3184 "\n"
3185 "\n"
3186 "#ifdef MODE_LIGHTDIRECTION\n"
3187 "#define SHADING\n"
3188 "#ifdef USEDIFFUSE\n"
3189 "       half3 lightnormal = half3(normalize(LightVector));\n"
3190 "#endif\n"
3191 "#define lightcolor LightColor\n"
3192 "#endif // MODE_LIGHTDIRECTION\n"
3193 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3194 "#define SHADING\n"
3195 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3196 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3197 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3198 "       // convert modelspace light vector to tangentspace\n"
3199 "       half3 lightnormal;\n"
3200 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3201 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3202 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3203 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3204 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3205 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3206 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3207 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3208 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3209 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3210 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3211 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3212 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3213 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3214 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3215 "#define SHADING\n"
3216 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3217 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3218 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3219 "#endif\n"
3220 "\n"
3221 "\n"
3222 "\n"
3223 "\n"
3224 "#ifdef MODE_FAKELIGHT\n"
3225 "#define SHADING\n"
3226 "half3 lightnormal = half3(normalize(EyeVector));\n"
3227 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3228 "#endif // MODE_FAKELIGHT\n"
3229 "\n"
3230 "\n"
3231 "\n"
3232 "\n"
3233 "#ifdef MODE_LIGHTMAP\n"
3234 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3235 "#endif // MODE_LIGHTMAP\n"
3236 "#ifdef MODE_VERTEXCOLOR\n"
3237 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3238 "#endif // MODE_VERTEXCOLOR\n"
3239 "#ifdef MODE_FLATCOLOR\n"
3240 "       color.rgb = diffusetex * Color_Ambient;\n"
3241 "#endif // MODE_FLATCOLOR\n"
3242 "\n"
3243 "\n"
3244 "\n"
3245 "\n"
3246 "#ifdef SHADING\n"
3247 "# ifdef USEDIFFUSE\n"
3248 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3249 "#  ifdef USESPECULAR\n"
3250 "#   ifdef USEEXACTSPECULARMATH\n"
3251 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3252 "#   else\n"
3253 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3254 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3255 "#   endif\n"
3256 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3257 "#  else\n"
3258 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3259 "#  endif\n"
3260 "# else\n"
3261 "       color.rgb = diffusetex * Color_Ambient;\n"
3262 "# endif\n"
3263 "#endif\n"
3264 "\n"
3265 "#ifdef USESHADOWMAPORTHO\n"
3266 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3267 "#endif\n"
3268 "\n"
3269 "#ifdef USEDEFERREDLIGHTMAP\n"
3270 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3271 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3272 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3273 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3274 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3275 "#endif\n"
3276 "\n"
3277 "#ifdef USEGLOW\n"
3278 "#ifdef USEVERTEXTEXTUREBLEND\n"
3279 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3280 "#else\n"
3281 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3282 "#endif\n"
3283 "#endif\n"
3284 "\n"
3285 "#ifdef USEFOG\n"
3286 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3287 "#endif\n"
3288 "\n"
3289 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
3290 "#ifdef USEREFLECTION\n"
3291 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3292 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3293 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3294 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3295 "       // FIXME temporary hack to detect the case that the reflection\n"
3296 "       // gets blackened at edges due to leaving the area that contains actual\n"
3297 "       // content.\n"
3298 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3299 "       // 'appening.\n"
3300 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3301 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3302 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3303 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3304 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3305 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3306 "#endif\n"
3307 "\n"
3308 "       gl_FragColor = float4(color);\n"
3309 "}\n"
3310 "#endif // FRAGMENT_SHADER\n"
3311 "\n"
3312 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3313 "#endif // !MODE_DEFERREDGEOMETRY\n"
3314 "#endif // !MODE_WATER\n"
3315 "#endif // !MODE_REFRACTION\n"
3316 "#endif // !MODE_BLOOMBLUR\n"
3317 "#endif // !MODE_GENERIC\n"
3318 "#endif // !MODE_POSTPROCESS\n"
3319 "#endif // !MODE_SHOWDEPTH\n"
3320 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3321 ;
3322
3323 /*
3324 =========================================================================================================================================================
3325
3326
3327
3328 =========================================================================================================================================================
3329
3330
3331
3332 =========================================================================================================================================================
3333
3334
3335
3336 =========================================================================================================================================================
3337
3338
3339
3340 =========================================================================================================================================================
3341
3342
3343
3344 =========================================================================================================================================================
3345
3346
3347
3348 =========================================================================================================================================================
3349 */
3350
3351 const char *builtingles2shaderstring = ""; // FIXME GLES2
3352
3353 char *glslshaderstring = NULL;
3354 char *cgshaderstring = NULL;
3355 char *hlslshaderstring = NULL;
3356
3357 //=======================================================================================================================================================
3358
3359 typedef struct shaderpermutationinfo_s
3360 {
3361         const char *pretext;
3362         const char *name;
3363 }
3364 shaderpermutationinfo_t;
3365
3366 typedef struct shadermodeinfo_s
3367 {
3368         const char *vertexfilename;
3369         const char *geometryfilename;
3370         const char *fragmentfilename;
3371         const char *pretext;
3372         const char *name;
3373 }
3374 shadermodeinfo_t;
3375
3376 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3377 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3378 {
3379         {"#define USEDIFFUSE\n", " diffuse"},
3380         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3381         {"#define USEVIEWTINT\n", " viewtint"},
3382         {"#define USECOLORMAPPING\n", " colormapping"},
3383         {"#define USESATURATION\n", " saturation"},
3384         {"#define USEFOGINSIDE\n", " foginside"},
3385         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3386         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3387         {"#define USEGAMMARAMPS\n", " gammaramps"},
3388         {"#define USECUBEFILTER\n", " cubefilter"},
3389         {"#define USEGLOW\n", " glow"},
3390         {"#define USEBLOOM\n", " bloom"},
3391         {"#define USESPECULAR\n", " specular"},
3392         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3393         {"#define USEREFLECTION\n", " reflection"},
3394         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3395         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3396         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3397         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3398         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3399         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3400         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3401         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3402         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3403         {"#define USEALPHAKILL\n", " alphakill"},
3404         {"#define USEREFLECTCUBE\n", " reflectcube"},
3405         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3406 };
3407
3408 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3409 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3410 {
3411         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3412         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3413         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3414         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3415         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3416         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3417         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3418         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3419         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3420         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3421         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3422         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3423         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3424         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3425         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3426         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3427 };
3428
3429 #ifdef SUPPORTCG
3430 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3431 {
3432         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3433         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3434         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3435         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3436         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3437         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3438         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3439         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3440         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3441         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3442         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3443         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3444         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3445         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3446         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3447         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3448 };
3449 #endif
3450
3451 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3452 {
3453         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3454         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3455         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3456         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3457         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3458         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3459         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3460         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3461         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3462         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3463         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3464         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3465         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3466         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3467         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3468         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3469 };
3470
3471 shadermodeinfo_t gles2shadermodeinfo[SHADERMODE_COUNT] =
3472 {
3473         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_GENERIC\n", " generic"},
3474         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3475         {"gles2/default.glsl", NULL, NULL                , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3476         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3477         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3478         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3479         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3480         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3481         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3482         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3483         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3484         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3485         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_WATER\n", " water"},
3486         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3487         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3488         {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3489 };
3490
3491 struct r_glsl_permutation_s;
3492 typedef struct r_glsl_permutation_s
3493 {
3494         /// hash lookup data
3495         struct r_glsl_permutation_s *hashnext;
3496         unsigned int mode;
3497         unsigned int permutation;
3498
3499         /// indicates if we have tried compiling this permutation already
3500         qboolean compiled;
3501         /// 0 if compilation failed
3502         int program;
3503         // texture units assigned to each detected uniform
3504         int tex_Texture_First;
3505         int tex_Texture_Second;
3506         int tex_Texture_GammaRamps;
3507         int tex_Texture_Normal;
3508         int tex_Texture_Color;
3509         int tex_Texture_Gloss;
3510         int tex_Texture_Glow;
3511         int tex_Texture_SecondaryNormal;
3512         int tex_Texture_SecondaryColor;
3513         int tex_Texture_SecondaryGloss;
3514         int tex_Texture_SecondaryGlow;
3515         int tex_Texture_Pants;
3516         int tex_Texture_Shirt;
3517         int tex_Texture_FogHeightTexture;
3518         int tex_Texture_FogMask;
3519         int tex_Texture_Lightmap;
3520         int tex_Texture_Deluxemap;
3521         int tex_Texture_Attenuation;
3522         int tex_Texture_Cube;
3523         int tex_Texture_Refraction;
3524         int tex_Texture_Reflection;
3525         int tex_Texture_ShadowMap2D;
3526         int tex_Texture_CubeProjection;
3527         int tex_Texture_ScreenDepth;
3528         int tex_Texture_ScreenNormalMap;
3529         int tex_Texture_ScreenDiffuse;
3530         int tex_Texture_ScreenSpecular;
3531         int tex_Texture_ReflectMask;
3532         int tex_Texture_ReflectCube;
3533         /// locations of detected uniforms in program object, or -1 if not found
3534         int loc_Texture_First;
3535         int loc_Texture_Second;
3536         int loc_Texture_GammaRamps;
3537         int loc_Texture_Normal;
3538         int loc_Texture_Color;
3539         int loc_Texture_Gloss;
3540         int loc_Texture_Glow;
3541         int loc_Texture_SecondaryNormal;
3542         int loc_Texture_SecondaryColor;
3543         int loc_Texture_SecondaryGloss;
3544         int loc_Texture_SecondaryGlow;
3545         int loc_Texture_Pants;
3546         int loc_Texture_Shirt;
3547         int loc_Texture_FogHeightTexture;
3548         int loc_Texture_FogMask;
3549         int loc_Texture_Lightmap;
3550         int loc_Texture_Deluxemap;
3551         int loc_Texture_Attenuation;
3552         int loc_Texture_Cube;
3553         int loc_Texture_Refraction;
3554         int loc_Texture_Reflection;
3555         int loc_Texture_ShadowMap2D;
3556         int loc_Texture_CubeProjection;
3557         int loc_Texture_ScreenDepth;
3558         int loc_Texture_ScreenNormalMap;
3559         int loc_Texture_ScreenDiffuse;
3560         int loc_Texture_ScreenSpecular;
3561         int loc_Texture_ReflectMask;
3562         int loc_Texture_ReflectCube;
3563         int loc_Alpha;
3564         int loc_BloomBlur_Parameters;
3565         int loc_ClientTime;
3566         int loc_Color_Ambient;
3567         int loc_Color_Diffuse;
3568         int loc_Color_Specular;
3569         int loc_Color_Glow;
3570         int loc_Color_Pants;
3571         int loc_Color_Shirt;
3572         int loc_DeferredColor_Ambient;
3573         int loc_DeferredColor_Diffuse;
3574         int loc_DeferredColor_Specular;
3575         int loc_DeferredMod_Diffuse;
3576         int loc_DeferredMod_Specular;
3577         int loc_DistortScaleRefractReflect;
3578         int loc_EyePosition;
3579         int loc_FogColor;
3580         int loc_FogHeightFade;
3581         int loc_FogPlane;
3582         int loc_FogPlaneViewDist;
3583         int loc_FogRangeRecip;
3584         int loc_LightColor;
3585         int loc_LightDir;
3586         int loc_LightPosition;
3587         int loc_OffsetMapping_Scale;
3588         int loc_PixelSize;
3589         int loc_ReflectColor;
3590         int loc_ReflectFactor;
3591         int loc_ReflectOffset;
3592         int loc_RefractColor;
3593         int loc_Saturation;
3594         int loc_ScreenCenterRefractReflect;
3595         int loc_ScreenScaleRefractReflect;
3596         int loc_ScreenToDepth;
3597         int loc_ShadowMap_Parameters;
3598         int loc_ShadowMap_TextureScale;
3599         int loc_SpecularPower;
3600         int loc_UserVec1;
3601         int loc_UserVec2;
3602         int loc_UserVec3;
3603         int loc_UserVec4;
3604         int loc_ViewTintColor;
3605         int loc_ViewToLight;
3606         int loc_ModelToLight;
3607         int loc_TexMatrix;
3608         int loc_BackgroundTexMatrix;
3609         int loc_ModelViewProjectionMatrix;
3610         int loc_ModelViewMatrix;
3611         int loc_PixelToScreenTexCoord;
3612         int loc_ModelToReflectCube;
3613         int loc_ShadowMapMatrix;
3614         int loc_BloomColorSubtract;
3615         int loc_NormalmapScrollBlend;
3616 }
3617 r_glsl_permutation_t;
3618
3619 #define SHADERPERMUTATION_HASHSIZE 256
3620
3621
3622 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3623 // these can NOT degrade! only use for simple stuff
3624 enum
3625 {
3626         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3627         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3628         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3629         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3630         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3631         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
3632 };
3633 #define SHADERSTATICPARMS_COUNT 6
3634
3635 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3636 static int shaderstaticparms_count = 0;
3637
3638 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3639 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3640 qboolean R_CompileShader_CheckStaticParms(void)
3641 {
3642         static int r_compileshader_staticparms_save[1];
3643         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3644         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3645
3646         // detect all
3647         if (r_glsl_saturation_redcompensate.integer)
3648                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3649         if (r_shadow_glossexact.integer)
3650                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3651         if (r_glsl_postprocess.integer)
3652         {
3653                 if (r_glsl_postprocess_uservec1_enable.integer)
3654                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3655                 if (r_glsl_postprocess_uservec2_enable.integer)
3656                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3657                 if (r_glsl_postprocess_uservec3_enable.integer)
3658                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3659                 if (r_glsl_postprocess_uservec4_enable.integer)
3660                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3661         }
3662         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3663 }
3664
3665 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3666         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3667                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3668         else \
3669                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3670 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3671 {
3672         shaderstaticparms_count = 0;
3673
3674         // emit all
3675         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3676         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3677         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3678         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3679         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3680         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3681 }
3682
3683 /// information about each possible shader permutation
3684 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3685 /// currently selected permutation
3686 r_glsl_permutation_t *r_glsl_permutation;
3687 /// storage for permutations linked in the hash table
3688 memexpandablearray_t r_glsl_permutationarray;
3689
3690 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3691 {
3692         //unsigned int hashdepth = 0;
3693         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3694         r_glsl_permutation_t *p;
3695         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3696         {
3697                 if (p->mode == mode && p->permutation == permutation)
3698                 {
3699                         //if (hashdepth > 10)
3700                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3701                         return p;
3702                 }
3703                 //hashdepth++;
3704         }
3705         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3706         p->mode = mode;
3707         p->permutation = permutation;
3708         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3709         r_glsl_permutationhash[mode][hashindex] = p;
3710         //if (hashdepth > 10)
3711         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3712         return p;
3713 }
3714
3715 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3716 {
3717         char *shaderstring;
3718         if (!filename || !filename[0])
3719                 return NULL;
3720         if (!strcmp(filename, "glsl/default.glsl"))
3721         {
3722                 if (!glslshaderstring)
3723                 {
3724                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3725                         if (glslshaderstring)
3726                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3727                         else
3728                                 glslshaderstring = (char *)builtinshaderstring;
3729                 }
3730                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3731                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3732                 return shaderstring;
3733         }
3734         if (!strcmp(filename, "gles2/default.glsl"))
3735         {
3736                 if (!glslshaderstring)
3737                 {
3738                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3739                         if (glslshaderstring)
3740                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3741                         else
3742                                 glslshaderstring = (char *)builtingles2shaderstring;
3743                 }
3744                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3745                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3746                 return shaderstring;
3747         }
3748         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3749         if (shaderstring)
3750         {
3751                 if (printfromdisknotice)
3752                         Con_DPrintf("from disk %s... ", filename);
3753                 return shaderstring;
3754         }
3755         return shaderstring;
3756 }
3757
3758 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3759 {
3760         int i;
3761         int sampler;
3762         shadermodeinfo_t *modeinfo = vid.renderpath == RENDERPATH_GLES2 ? gles2shadermodeinfo + mode : glslshadermodeinfo + mode;
3763         char *vertexstring, *geometrystring, *fragmentstring;
3764         char permutationname[256];
3765         int vertstrings_count = 0;
3766         int geomstrings_count = 0;
3767         int fragstrings_count = 0;
3768         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3769         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3770         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3771
3772         if (p->compiled)
3773                 return;
3774         p->compiled = true;
3775         p->program = 0;
3776
3777         permutationname[0] = 0;
3778         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3779         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3780         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3781
3782         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3783
3784         // the first pretext is which type of shader to compile as
3785         // (later these will all be bound together as a program object)
3786         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3787         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3788         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3789
3790         // the second pretext is the mode (for example a light source)
3791         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3792         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3793         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3794         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3795
3796         // now add all the permutation pretexts
3797         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3798         {
3799                 if (permutation & (1<<i))
3800                 {
3801                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3802                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3803                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3804                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3805                 }
3806                 else
3807                 {
3808                         // keep line numbers correct
3809                         vertstrings_list[vertstrings_count++] = "\n";
3810                         geomstrings_list[geomstrings_count++] = "\n";
3811                         fragstrings_list[fragstrings_count++] = "\n";
3812                 }
3813         }
3814
3815         // add static parms
3816         R_CompileShader_AddStaticParms(mode, permutation);
3817         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3818         vertstrings_count += shaderstaticparms_count;
3819         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3820         geomstrings_count += shaderstaticparms_count;
3821         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3822         fragstrings_count += shaderstaticparms_count;
3823
3824         // now append the shader text itself
3825         vertstrings_list[vertstrings_count++] = vertexstring;
3826         geomstrings_list[geomstrings_count++] = geometrystring;
3827         fragstrings_list[fragstrings_count++] = fragmentstring;
3828
3829         // if any sources were NULL, clear the respective list
3830         if (!vertexstring)
3831                 vertstrings_count = 0;
3832         if (!geometrystring)
3833                 geomstrings_count = 0;
3834         if (!fragmentstring)
3835                 fragstrings_count = 0;
3836
3837         // compile the shader program
3838         if (vertstrings_count + geomstrings_count + fragstrings_count)
3839                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3840         if (p->program)
3841         {
3842                 CHECKGLERROR
3843                 qglUseProgram(p->program);CHECKGLERROR
3844                 // look up all the uniform variable names we care about, so we don't
3845                 // have to look them up every time we set them
3846
3847                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
3848                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
3849                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
3850                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
3851                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
3852                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
3853                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
3854                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
3855                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
3856                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
3857                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
3858                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
3859                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
3860                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
3861                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
3862                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
3863                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
3864                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
3865                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
3866                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
3867                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
3868                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
3869                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
3870                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
3871                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
3872                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
3873                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
3874                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
3875                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
3876                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
3877                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
3878                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
3879                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
3880                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
3881                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
3882                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
3883                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
3884                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
3885                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
3886                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
3887                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
3888                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
3889                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
3890                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
3891                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
3892                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
3893                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
3894                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
3895                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
3896                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
3897                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
3898                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
3899                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
3900                 p->loc_OffsetMapping_Scale        = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
3901                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
3902                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
3903                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
3904                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
3905                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
3906                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
3907                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
3908                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
3909                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
3910                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
3911                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
3912                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
3913                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
3914                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
3915                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
3916                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
3917                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
3918                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
3919                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
3920                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
3921                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
3922                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
3923                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
3924                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
3925                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
3926                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
3927                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
3928                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
3929                 // initialize the samplers to refer to the texture units we use
3930                 p->tex_Texture_First = -1;
3931                 p->tex_Texture_Second = -1;
3932                 p->tex_Texture_GammaRamps = -1;
3933                 p->tex_Texture_Normal = -1;
3934                 p->tex_Texture_Color = -1;
3935                 p->tex_Texture_Gloss = -1;
3936                 p->tex_Texture_Glow = -1;
3937                 p->tex_Texture_SecondaryNormal = -1;
3938                 p->tex_Texture_SecondaryColor = -1;
3939                 p->tex_Texture_SecondaryGloss = -1;
3940                 p->tex_Texture_SecondaryGlow = -1;
3941                 p->tex_Texture_Pants = -1;
3942                 p->tex_Texture_Shirt = -1;
3943                 p->tex_Texture_FogHeightTexture = -1;
3944                 p->tex_Texture_FogMask = -1;
3945                 p->tex_Texture_Lightmap = -1;
3946                 p->tex_Texture_Deluxemap = -1;
3947                 p->tex_Texture_Attenuation = -1;
3948                 p->tex_Texture_Cube = -1;
3949                 p->tex_Texture_Refraction = -1;
3950                 p->tex_Texture_Reflection = -1;
3951                 p->tex_Texture_ShadowMap2D = -1;
3952                 p->tex_Texture_CubeProjection = -1;
3953                 p->tex_Texture_ScreenDepth = -1;
3954                 p->tex_Texture_ScreenNormalMap = -1;
3955                 p->tex_Texture_ScreenDiffuse = -1;
3956                 p->tex_Texture_ScreenSpecular = -1;
3957                 p->tex_Texture_ReflectMask = -1;
3958                 p->tex_Texture_ReflectCube = -1;
3959                 sampler = 0;
3960                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
3961                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
3962                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
3963                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
3964                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
3965                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
3966                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
3967                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
3968                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
3969                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
3970                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
3971                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
3972                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
3973                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
3974                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
3975                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
3976                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
3977                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
3978                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
3979                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
3980                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
3981                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
3982                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
3983                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
3984                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
3985                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
3986                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
3987                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
3988                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
3989                 if (vid.renderpath == RENDERPATH_GLES2)
3990                 {
3991                         qglBindAttribLocation(p->program, GLES2ATTRIB_POSITION , "Attrib_Position" );
3992                         qglBindAttribLocation(p->program, GLES2ATTRIB_COLOR    , "Attrib_Color"    );
3993                         qglBindAttribLocation(p->program, GLES2ATTRIB_TEXCOORD0, "Attrib_TexCoord0");
3994                         qglBindAttribLocation(p->program, GLES2ATTRIB_TEXCOORD1, "Attrib_TexCoord1");
3995                         qglBindAttribLocation(p->program, GLES2ATTRIB_TEXCOORD2, "Attrib_TexCoord2");
3996                         qglBindAttribLocation(p->program, GLES2ATTRIB_TEXCOORD3, "Attrib_TexCoord3");
3997                         qglBindAttribLocation(p->program, GLES2ATTRIB_TEXCOORD4, "Attrib_TexCoord4");
3998                         qglBindAttribLocation(p->program, GLES2ATTRIB_TEXCOORD5, "Attrib_TexCoord5");
3999                         qglBindAttribLocation(p->program, GLES2ATTRIB_TEXCOORD6, "Attrib_TexCoord6");
4000                         qglBindAttribLocation(p->program, GLES2ATTRIB_TEXCOORD7, "Attrib_TexCoord7");
4001                 }
4002                 CHECKGLERROR
4003                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
4004         }
4005         else
4006                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
4007
4008         // free the strings
4009         if (vertexstring)
4010                 Mem_Free(vertexstring);
4011         if (geometrystring)
4012                 Mem_Free(geometrystring);
4013         if (fragmentstring)
4014                 Mem_Free(fragmentstring);
4015 }
4016
4017 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
4018 {
4019         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
4020         if (r_glsl_permutation != perm)
4021         {
4022                 r_glsl_permutation = perm;
4023                 if (!r_glsl_permutation->program)
4024                 {
4025                         if (!r_glsl_permutation->compiled)
4026                                 R_GLSL_CompilePermutation(perm, mode, permutation);
4027                         if (!r_glsl_permutation->program)
4028                         {
4029                                 // remove features until we find a valid permutation
4030                                 int i;
4031                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4032                                 {
4033                                         // reduce i more quickly whenever it would not remove any bits
4034                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4035                                         if (!(permutation & j))
4036                                                 continue;
4037                                         permutation -= j;
4038                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4039                                         if (!r_glsl_permutation->compiled)
4040                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
4041                                         if (r_glsl_permutation->program)
4042                                                 break;
4043                                 }
4044                                 if (i >= SHADERPERMUTATION_COUNT)
4045                                 {
4046                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4047                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4048                                         qglUseProgram(0);CHECKGLERROR
4049                                         return; // no bit left to clear, entire mode is broken
4050                                 }
4051                         }
4052                 }
4053                 CHECKGLERROR
4054                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
4055         }
4056         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4057         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4058         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
4059 }
4060
4061 #ifdef SUPPORTCG
4062 #include <Cg/cgGL.h>
4063 struct r_cg_permutation_s;
4064 typedef struct r_cg_permutation_s
4065 {
4066         /// hash lookup data
4067         struct r_cg_permutation_s *hashnext;
4068         unsigned int mode;
4069         unsigned int permutation;
4070
4071         /// indicates if we have tried compiling this permutation already
4072         qboolean compiled;
4073         /// 0 if compilation failed
4074         CGprogram vprogram;
4075         CGprogram fprogram;
4076         /// locations of detected parameters in programs, or NULL if not found
4077         CGparameter vp_EyePosition;
4078         CGparameter vp_FogPlane;
4079         CGparameter vp_LightDir;
4080         CGparameter vp_LightPosition;
4081         CGparameter vp_ModelToLight;
4082         CGparameter vp_TexMatrix;
4083         CGparameter vp_BackgroundTexMatrix;
4084         CGparameter vp_ModelViewProjectionMatrix;
4085         CGparameter vp_ModelViewMatrix;
4086         CGparameter vp_ShadowMapMatrix;
4087
4088         CGparameter fp_Texture_First;
4089         CGparameter fp_Texture_Second;
4090         CGparameter fp_Texture_GammaRamps;
4091         CGparameter fp_Texture_Normal;
4092         CGparameter fp_Texture_Color;
4093         CGparameter fp_Texture_Gloss;
4094         CGparameter fp_Texture_Glow;
4095         CGparameter fp_Texture_SecondaryNormal;
4096         CGparameter fp_Texture_SecondaryColor;
4097         CGparameter fp_Texture_SecondaryGloss;
4098         CGparameter fp_Texture_SecondaryGlow;
4099         CGparameter fp_Texture_Pants;
4100         CGparameter fp_Texture_Shirt;
4101         CGparameter fp_Texture_FogHeightTexture;
4102         CGparameter fp_Texture_FogMask;
4103         CGparameter fp_Texture_Lightmap;
4104         CGparameter fp_Texture_Deluxemap;
4105         CGparameter fp_Texture_Attenuation;
4106         CGparameter fp_Texture_Cube;
4107         CGparameter fp_Texture_Refraction;
4108         CGparameter fp_Texture_Reflection;
4109         CGparameter fp_Texture_ShadowMap2D;
4110         CGparameter fp_Texture_CubeProjection;
4111         CGparameter fp_Texture_ScreenDepth;
4112         CGparameter fp_Texture_ScreenNormalMap;
4113         CGparameter fp_Texture_ScreenDiffuse;
4114         CGparameter fp_Texture_ScreenSpecular;
4115         CGparameter fp_Texture_ReflectMask;
4116         CGparameter fp_Texture_ReflectCube;
4117         CGparameter fp_Alpha;
4118         CGparameter fp_BloomBlur_Parameters;
4119         CGparameter fp_ClientTime;
4120         CGparameter fp_Color_Ambient;
4121         CGparameter fp_Color_Diffuse;
4122         CGparameter fp_Color_Specular;
4123         CGparameter fp_Color_Glow;
4124         CGparameter fp_Color_Pants;
4125         CGparameter fp_Color_Shirt;
4126         CGparameter fp_DeferredColor_Ambient;
4127         CGparameter fp_DeferredColor_Diffuse;
4128         CGparameter fp_DeferredColor_Specular;
4129         CGparameter fp_DeferredMod_Diffuse;
4130         CGparameter fp_DeferredMod_Specular;
4131         CGparameter fp_DistortScaleRefractReflect;
4132         CGparameter fp_EyePosition;
4133         CGparameter fp_FogColor;
4134         CGparameter fp_FogHeightFade;
4135         CGparameter fp_FogPlane;
4136         CGparameter fp_FogPlaneViewDist;
4137         CGparameter fp_FogRangeRecip;
4138         CGparameter fp_LightColor;
4139         CGparameter fp_LightDir;
4140         CGparameter fp_LightPosition;
4141         CGparameter fp_OffsetMapping_Scale;
4142         CGparameter fp_PixelSize;
4143         CGparameter fp_ReflectColor;
4144         CGparameter fp_ReflectFactor;
4145         CGparameter fp_ReflectOffset;
4146         CGparameter fp_RefractColor;
4147         CGparameter fp_Saturation;
4148         CGparameter fp_ScreenCenterRefractReflect;
4149         CGparameter fp_ScreenScaleRefractReflect;
4150         CGparameter fp_ScreenToDepth;
4151         CGparameter fp_ShadowMap_Parameters;
4152         CGparameter fp_ShadowMap_TextureScale;
4153         CGparameter fp_SpecularPower;
4154         CGparameter fp_UserVec1;
4155         CGparameter fp_UserVec2;
4156         CGparameter fp_UserVec3;
4157         CGparameter fp_UserVec4;
4158         CGparameter fp_ViewTintColor;
4159         CGparameter fp_ViewToLight;
4160         CGparameter fp_PixelToScreenTexCoord;
4161         CGparameter fp_ModelToReflectCube;
4162         CGparameter fp_BloomColorSubtract;
4163         CGparameter fp_NormalmapScrollBlend;
4164 }
4165 r_cg_permutation_t;
4166
4167 /// information about each possible shader permutation
4168 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4169 /// currently selected permutation
4170 r_cg_permutation_t *r_cg_permutation;
4171 /// storage for permutations linked in the hash table
4172 memexpandablearray_t r_cg_permutationarray;
4173
4174 #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));}}
4175
4176 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4177 {
4178         //unsigned int hashdepth = 0;
4179         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4180         r_cg_permutation_t *p;
4181         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4182         {
4183                 if (p->mode == mode && p->permutation == permutation)
4184                 {
4185                         //if (hashdepth > 10)
4186                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4187                         return p;
4188                 }
4189                 //hashdepth++;
4190         }
4191         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4192         p->mode = mode;
4193         p->permutation = permutation;
4194         p->hashnext = r_cg_permutationhash[mode][hashindex];
4195         r_cg_permutationhash[mode][hashindex] = p;
4196         //if (hashdepth > 10)
4197         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4198         return p;
4199 }
4200
4201 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4202 {
4203         char *shaderstring;
4204         if (!filename || !filename[0])
4205                 return NULL;
4206         if (!strcmp(filename, "cg/default.cg"))
4207         {
4208                 if (!cgshaderstring)
4209                 {
4210                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4211                         if (cgshaderstring)
4212                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4213                         else
4214                                 cgshaderstring = (char *)builtincgshaderstring;
4215                 }
4216                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4217                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4218                 return shaderstring;
4219         }
4220         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4221         if (shaderstring)
4222         {
4223                 if (printfromdisknotice)
4224                         Con_DPrintf("from disk %s... ", filename);
4225                 return shaderstring;
4226         }
4227         return shaderstring;
4228 }
4229
4230 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4231 {
4232         // TODO: load or create .fp and .vp shader files
4233 }
4234
4235 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4236 {
4237         int i;
4238         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4239         int vertstring_length = 0;
4240         int geomstring_length = 0;
4241         int fragstring_length = 0;
4242         char *t;
4243         char *vertexstring, *geometrystring, *fragmentstring;
4244         char *vertstring, *geomstring, *fragstring;
4245         char permutationname[256];
4246         char cachename[256];
4247         CGprofile vertexProfile;
4248         CGprofile fragmentProfile;
4249         int vertstrings_count = 0;
4250         int geomstrings_count = 0;
4251         int fragstrings_count = 0;
4252         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4253         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4254         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4255
4256         if (p->compiled)
4257                 return;
4258         p->compiled = true;
4259         p->vprogram = NULL;
4260         p->fprogram = NULL;
4261
4262         permutationname[0] = 0;
4263         cachename[0] = 0;
4264         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4265         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4266         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4267
4268         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4269         strlcat(cachename, "cg/", sizeof(cachename));
4270
4271         // the first pretext is which type of shader to compile as
4272         // (later these will all be bound together as a program object)
4273         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4274         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4275         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4276
4277         // the second pretext is the mode (for example a light source)
4278         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4279         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4280         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4281         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4282         strlcat(cachename, modeinfo->name, sizeof(cachename));
4283
4284         // now add all the permutation pretexts
4285         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4286         {
4287                 if (permutation & (1<<i))
4288                 {
4289                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4290                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4291                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4292                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4293                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4294                 }
4295                 else
4296                 {
4297                         // keep line numbers correct
4298                         vertstrings_list[vertstrings_count++] = "\n";
4299                         geomstrings_list[geomstrings_count++] = "\n";
4300                         fragstrings_list[fragstrings_count++] = "\n";
4301                 }
4302         }
4303
4304         // add static parms
4305         R_CompileShader_AddStaticParms(mode, permutation);
4306         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4307         vertstrings_count += shaderstaticparms_count;
4308         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4309         geomstrings_count += shaderstaticparms_count;
4310         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4311         fragstrings_count += shaderstaticparms_count;
4312
4313         // replace spaces in the cachename with _ characters
4314         for (i = 0;cachename[i];i++)
4315                 if (cachename[i] == ' ')
4316                         cachename[i] = '_';
4317
4318         // now append the shader text itself
4319         vertstrings_list[vertstrings_count++] = vertexstring;
4320         geomstrings_list[geomstrings_count++] = geometrystring;
4321         fragstrings_list[fragstrings_count++] = fragmentstring;
4322
4323         // if any sources were NULL, clear the respective list
4324         if (!vertexstring)
4325                 vertstrings_count = 0;
4326         if (!geometrystring)
4327                 geomstrings_count = 0;
4328         if (!fragmentstring)
4329                 fragstrings_count = 0;
4330
4331         vertstring_length = 0;
4332         for (i = 0;i < vertstrings_count;i++)
4333                 vertstring_length += strlen(vertstrings_list[i]);
4334         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4335         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4336                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4337
4338         geomstring_length = 0;
4339         for (i = 0;i < geomstrings_count;i++)
4340                 geomstring_length += strlen(geomstrings_list[i]);
4341         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4342         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4343                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4344
4345         fragstring_length = 0;
4346         for (i = 0;i < fragstrings_count;i++)
4347                 fragstring_length += strlen(fragstrings_list[i]);
4348         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4349         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4350                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4351
4352         CHECKGLERROR
4353         CHECKCGERROR
4354         //vertexProfile = CG_PROFILE_ARBVP1;
4355         //fragmentProfile = CG_PROFILE_ARBFP1;
4356         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4357         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4358         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4359         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4360         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4361         CHECKGLERROR
4362
4363         // try to load the cached shader, or generate one
4364         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4365
4366         // if caching failed, do a dynamic compile for now
4367         CHECKCGERROR
4368         if (vertstring[0] && !p->vprogram)
4369                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4370         CHECKCGERROR
4371         if (fragstring[0] && !p->fprogram)
4372                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4373         CHECKCGERROR
4374
4375         // look up all the uniform variable names we care about, so we don't
4376         // have to look them up every time we set them
4377         if (p->vprogram)
4378         {
4379                 CHECKCGERROR
4380                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4381                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4382                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4383                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4384                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4385                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4386                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4387                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4388                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4389                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4390                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4391                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4392                 CHECKCGERROR
4393         }
4394         if (p->fprogram)
4395         {
4396                 CHECKCGERROR
4397                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4398                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4399                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4400                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4401                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4402                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4403                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4404                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4405                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4406                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4407                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4408                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4409                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4410                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4411                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4412                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4413                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4414                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4415                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4416                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4417                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4418                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4419                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4420                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4421                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4422                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4423                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4424                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4425                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4426                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4427                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4428                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4429                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4430                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4431                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4432                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4433                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4434                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4435                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4436                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4437                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4438                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4439                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4440                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4441                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4442                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4443                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4444                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4445                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4446                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4447                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4448                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4449                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4450                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4451                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4452                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4453                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4454                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4455                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4456                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4457                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4458                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4459                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4460                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4461                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4462                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4463                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4464                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4465                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4466                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4467                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4468                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4469                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4470                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4471                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4472                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4473                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4474                 p->fp_NormalmapScrollBlend       = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4475                 CHECKCGERROR
4476         }
4477
4478         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4479                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4480         else
4481                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4482
4483         // free the strings
4484         if (vertstring)
4485                 Mem_Free(vertstring);
4486         if (geomstring)
4487                 Mem_Free(geomstring);
4488         if (fragstring)
4489                 Mem_Free(fragstring);
4490         if (vertexstring)
4491                 Mem_Free(vertexstring);
4492         if (geometrystring)
4493                 Mem_Free(geometrystring);
4494         if (fragmentstring)
4495                 Mem_Free(fragmentstring);
4496 }
4497
4498 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4499 {
4500         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4501         CHECKGLERROR
4502         CHECKCGERROR
4503         if (r_cg_permutation != perm)
4504         {
4505                 r_cg_permutation = perm;
4506                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4507                 {
4508                         if (!r_cg_permutation->compiled)
4509                                 R_CG_CompilePermutation(perm, mode, permutation);
4510                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4511                         {
4512                                 // remove features until we find a valid permutation
4513                                 int i;
4514                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4515                                 {
4516                                         // reduce i more quickly whenever it would not remove any bits
4517                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4518                                         if (!(permutation & j))
4519                                                 continue;
4520                                         permutation -= j;
4521                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4522                                         if (!r_cg_permutation->compiled)
4523                                                 R_CG_CompilePermutation(perm, mode, permutation);
4524                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4525                                                 break;
4526                                 }
4527                                 if (i >= SHADERPERMUTATION_COUNT)
4528                                 {
4529                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4530                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4531                                         return; // no bit left to clear, entire mode is broken
4532                                 }
4533                         }
4534                 }
4535                 CHECKGLERROR
4536                 CHECKCGERROR
4537                 if (r_cg_permutation->vprogram)
4538                 {
4539                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4540                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4541                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4542                 }
4543                 else
4544                 {
4545                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4546                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4547                 }
4548                 if (r_cg_permutation->fprogram)
4549                 {
4550                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4551                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4552                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4553                 }
4554                 else
4555                 {
4556                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4557                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4558                 }
4559         }
4560         CHECKCGERROR
4561         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4562         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4563         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4564 }
4565
4566 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4567 {
4568         cgGLSetTextureParameter(param, R_GetTexture(tex));
4569         cgGLEnableTextureParameter(param);
4570 }
4571 #endif
4572
4573 #ifdef SUPPORTD3D
4574
4575 #ifdef SUPPORTD3D
4576 #include <d3d9.h>
4577 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4578 extern D3DCAPS9 vid_d3d9caps;
4579 #endif
4580
4581 struct r_hlsl_permutation_s;
4582 typedef struct r_hlsl_permutation_s
4583 {
4584         /// hash lookup data
4585         struct r_hlsl_permutation_s *hashnext;
4586         unsigned int mode;
4587         unsigned int permutation;
4588
4589         /// indicates if we have tried compiling this permutation already
4590         qboolean compiled;
4591         /// NULL if compilation failed
4592         IDirect3DVertexShader9 *vertexshader;
4593         IDirect3DPixelShader9 *pixelshader;
4594 }
4595 r_hlsl_permutation_t;
4596
4597 typedef enum D3DVSREGISTER_e
4598 {
4599         D3DVSREGISTER_TexMatrix = 0, // float4x4
4600         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4601         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4602         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4603         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4604         D3DVSREGISTER_ModelToLight = 20, // float4x4
4605         D3DVSREGISTER_EyePosition = 24,
4606         D3DVSREGISTER_FogPlane = 25,
4607         D3DVSREGISTER_LightDir = 26,
4608         D3DVSREGISTER_LightPosition = 27,
4609 }
4610 D3DVSREGISTER_t;
4611
4612 typedef enum D3DPSREGISTER_e
4613 {
4614         D3DPSREGISTER_Alpha = 0,
4615         D3DPSREGISTER_BloomBlur_Parameters = 1,
4616         D3DPSREGISTER_ClientTime = 2,
4617         D3DPSREGISTER_Color_Ambient = 3,
4618         D3DPSREGISTER_Color_Diffuse = 4,
4619         D3DPSREGISTER_Color_Specular = 5,
4620         D3DPSREGISTER_Color_Glow = 6,
4621         D3DPSREGISTER_Color_Pants = 7,
4622         D3DPSREGISTER_Color_Shirt = 8,
4623         D3DPSREGISTER_DeferredColor_Ambient = 9,
4624         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4625         D3DPSREGISTER_DeferredColor_Specular = 11,
4626         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4627         D3DPSREGISTER_DeferredMod_Specular = 13,
4628         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4629         D3DPSREGISTER_EyePosition = 15, // unused
4630         D3DPSREGISTER_FogColor = 16,
4631         D3DPSREGISTER_FogHeightFade = 17,
4632         D3DPSREGISTER_FogPlane = 18,
4633         D3DPSREGISTER_FogPlaneViewDist = 19,
4634         D3DPSREGISTER_FogRangeRecip = 20,
4635         D3DPSREGISTER_LightColor = 21,
4636         D3DPSREGISTER_LightDir = 22, // unused
4637         D3DPSREGISTER_LightPosition = 23,
4638         D3DPSREGISTER_OffsetMapping_Scale = 24,
4639         D3DPSREGISTER_PixelSize = 25,
4640         D3DPSREGISTER_ReflectColor = 26,
4641         D3DPSREGISTER_ReflectFactor = 27,
4642         D3DPSREGISTER_ReflectOffset = 28,
4643         D3DPSREGISTER_RefractColor = 29,
4644         D3DPSREGISTER_Saturation = 30,
4645         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4646         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4647         D3DPSREGISTER_ScreenToDepth = 33,
4648         D3DPSREGISTER_ShadowMap_Parameters = 34,
4649         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4650         D3DPSREGISTER_SpecularPower = 36,
4651         D3DPSREGISTER_UserVec1 = 37,
4652         D3DPSREGISTER_UserVec2 = 38,
4653         D3DPSREGISTER_UserVec3 = 39,
4654         D3DPSREGISTER_UserVec4 = 40,
4655         D3DPSREGISTER_ViewTintColor = 41,
4656         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4657         D3DPSREGISTER_BloomColorSubtract = 43,
4658         D3DPSREGISTER_ViewToLight = 44, // float4x4
4659         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4660         D3DPSREGISTER_NormalmapScrollBlend = 52,
4661         // next at 53
4662 }
4663 D3DPSREGISTER_t;
4664
4665 /// information about each possible shader permutation
4666 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4667 /// currently selected permutation
4668 r_hlsl_permutation_t *r_hlsl_permutation;
4669 /// storage for permutations linked in the hash table
4670 memexpandablearray_t r_hlsl_permutationarray;
4671
4672 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4673 {
4674         //unsigned int hashdepth = 0;
4675         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4676         r_hlsl_permutation_t *p;
4677         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4678         {
4679                 if (p->mode == mode && p->permutation == permutation)
4680                 {
4681                         //if (hashdepth > 10)
4682                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4683                         return p;
4684                 }
4685                 //hashdepth++;
4686         }
4687         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4688         p->mode = mode;
4689         p->permutation = permutation;
4690         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4691         r_hlsl_permutationhash[mode][hashindex] = p;
4692         //if (hashdepth > 10)
4693         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4694         return p;
4695 }
4696
4697 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4698 {
4699         char *shaderstring;
4700         if (!filename || !filename[0])
4701                 return NULL;
4702         if (!strcmp(filename, "hlsl/default.hlsl"))
4703         {
4704                 if (!hlslshaderstring)
4705                 {
4706                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4707                         if (hlslshaderstring)
4708                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4709                         else
4710                                 hlslshaderstring = (char *)builtincgshaderstring;
4711                 }
4712                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4713                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4714                 return shaderstring;
4715         }
4716         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4717         if (shaderstring)
4718         {
4719                 if (printfromdisknotice)
4720                         Con_DPrintf("from disk %s... ", filename);
4721                 return shaderstring;
4722         }
4723         return shaderstring;
4724 }
4725
4726 #include <d3dx9.h>
4727 //#include <d3dx9shader.h>
4728 //#include <d3dx9mesh.h>
4729
4730 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4731 {
4732         DWORD *vsbin = NULL;
4733         DWORD *psbin = NULL;
4734         fs_offset_t vsbinsize;
4735         fs_offset_t psbinsize;
4736 //      IDirect3DVertexShader9 *vs = NULL;
4737 //      IDirect3DPixelShader9 *ps = NULL;
4738         ID3DXBuffer *vslog = NULL;
4739         ID3DXBuffer *vsbuffer = NULL;
4740         ID3DXConstantTable *vsconstanttable = NULL;
4741         ID3DXBuffer *pslog = NULL;
4742         ID3DXBuffer *psbuffer = NULL;
4743         ID3DXConstantTable *psconstanttable = NULL;
4744         int vsresult = 0;
4745         int psresult = 0;
4746         char temp[MAX_INPUTLINE];
4747         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4748         qboolean debugshader = gl_paranoid.integer != 0;
4749         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4750         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4751         if (!debugshader)
4752         {
4753                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4754                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4755         }
4756         if ((!vsbin && vertstring) || (!psbin && fragstring))
4757         {
4758                 const char* dllnames_d3dx9 [] =
4759                 {
4760                         "d3dx9_43.dll",
4761                         "d3dx9_42.dll",
4762                         "d3dx9_41.dll",
4763                         "d3dx9_40.dll",
4764                         "d3dx9_39.dll",
4765                         "d3dx9_38.dll",
4766                         "d3dx9_37.dll",
4767                         "d3dx9_36.dll",
4768                         "d3dx9_35.dll",
4769                         "d3dx9_34.dll",
4770                         "d3dx9_33.dll",
4771                         "d3dx9_32.dll",
4772                         "d3dx9_31.dll",
4773                         "d3dx9_30.dll",
4774                         "d3dx9_29.dll",
4775                         "d3dx9_28.dll",
4776                         "d3dx9_27.dll",
4777                         "d3dx9_26.dll",
4778                         "d3dx9_25.dll",
4779                         "d3dx9_24.dll",
4780                         NULL
4781                 };
4782                 dllhandle_t d3dx9_dll = NULL;
4783                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4784                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4785                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4786                 dllfunction_t d3dx9_dllfuncs[] =
4787                 {
4788                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4789                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4790                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4791                         {NULL, NULL}
4792                 };
4793                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4794                 {
4795                         DWORD shaderflags = 0;
4796                         if (debugshader)
4797                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4798                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4799                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4800                         if (vertstring && vertstring[0])
4801                         {
4802                                 if (debugshader)
4803                                 {
4804 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4805 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4806                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4807                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4808                                 }
4809                                 else
4810                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4811                                 if (vsbuffer)
4812                                 {
4813                                         vsbinsize = vsbuffer->GetBufferSize();
4814                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4815                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4816                                         vsbuffer->Release();
4817                                 }
4818                                 if (vslog)
4819                                 {
4820                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4821                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4822                                         vslog->Release();
4823                                 }
4824                         }
4825                         if (fragstring && fragstring[0])
4826                         {
4827                                 if (debugshader)
4828                                 {
4829 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4830 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4831                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4832                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4833                                 }
4834                                 else
4835                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4836                                 if (psbuffer)
4837                                 {
4838                                         psbinsize = psbuffer->GetBufferSize();
4839                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4840                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4841                                         psbuffer->Release();
4842                                 }
4843                                 if (pslog)
4844                                 {
4845                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4846                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4847                                         pslog->Release();
4848                                 }
4849                         }
4850                         Sys_UnloadLibrary(&d3dx9_dll);
4851                 }
4852                 else
4853                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4854         }
4855         if (vsbin && psbin)
4856         {
4857                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4858                 if (FAILED(vsresult))
4859                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4860                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4861                 if (FAILED(psresult))
4862                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4863         }
4864         // free the shader data
4865         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4866         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4867 }
4868
4869 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4870 {
4871         int i;
4872         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4873         int vertstring_length = 0;
4874         int geomstring_length = 0;
4875         int fragstring_length = 0;
4876         char *t;
4877         char *vertexstring, *geometrystring, *fragmentstring;
4878         char *vertstring, *geomstring, *fragstring;
4879         char permutationname[256];
4880         char cachename[256];
4881         int vertstrings_count = 0;
4882         int geomstrings_count = 0;
4883         int fragstrings_count = 0;
4884         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4885         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4886         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4887
4888         if (p->compiled)
4889                 return;
4890         p->compiled = true;
4891         p->vertexshader = NULL;
4892         p->pixelshader = NULL;
4893
4894         permutationname[0] = 0;
4895         cachename[0] = 0;
4896         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4897         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4898         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4899
4900         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4901         strlcat(cachename, "hlsl/", sizeof(cachename));
4902
4903         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4904         vertstrings_count = 0;
4905         geomstrings_count = 0;
4906         fragstrings_count = 0;
4907         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4908         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4909         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4910
4911         // the first pretext is which type of shader to compile as
4912         // (later these will all be bound together as a program object)
4913         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4914         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4915         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4916
4917         // the second pretext is the mode (for example a light source)
4918         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4919         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4920         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4921         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4922         strlcat(cachename, modeinfo->name, sizeof(cachename));
4923
4924         // now add all the permutation pretexts
4925         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4926         {
4927                 if (permutation & (1<<i))
4928                 {
4929                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4930                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4931                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4932                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4933                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4934                 }
4935                 else
4936                 {
4937                         // keep line numbers correct
4938                         vertstrings_list[vertstrings_count++] = "\n";
4939                         geomstrings_list[geomstrings_count++] = "\n";
4940                         fragstrings_list[fragstrings_count++] = "\n";
4941                 }
4942         }
4943
4944         // add static parms
4945         R_CompileShader_AddStaticParms(mode, permutation);
4946         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4947         vertstrings_count += shaderstaticparms_count;
4948         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4949         geomstrings_count += shaderstaticparms_count;
4950         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4951         fragstrings_count += shaderstaticparms_count;
4952
4953         // replace spaces in the cachename with _ characters
4954         for (i = 0;cachename[i];i++)
4955                 if (cachename[i] == ' ')
4956                         cachename[i] = '_';
4957
4958         // now append the shader text itself
4959         vertstrings_list[vertstrings_count++] = vertexstring;
4960         geomstrings_list[geomstrings_count++] = geometrystring;
4961         fragstrings_list[fragstrings_count++] = fragmentstring;
4962
4963         // if any sources were NULL, clear the respective list
4964         if (!vertexstring)
4965                 vertstrings_count = 0;
4966         if (!geometrystring)
4967                 geomstrings_count = 0;
4968         if (!fragmentstring)
4969                 fragstrings_count = 0;
4970
4971         vertstring_length = 0;
4972         for (i = 0;i < vertstrings_count;i++)
4973                 vertstring_length += strlen(vertstrings_list[i]);
4974         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4975         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4976                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4977
4978         geomstring_length = 0;
4979         for (i = 0;i < geomstrings_count;i++)
4980                 geomstring_length += strlen(geomstrings_list[i]);
4981         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4982         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4983                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4984
4985         fragstring_length = 0;
4986         for (i = 0;i < fragstrings_count;i++)
4987                 fragstring_length += strlen(fragstrings_list[i]);
4988         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4989         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4990                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4991
4992         // try to load the cached shader, or generate one
4993         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4994
4995         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4996                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4997         else
4998                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4999
5000         // free the strings
5001         if (vertstring)
5002                 Mem_Free(vertstring);
5003         if (geomstring)
5004                 Mem_Free(geomstring);
5005         if (fragstring)
5006                 Mem_Free(fragstring);
5007         if (vertexstring)
5008                 Mem_Free(vertexstring);
5009         if (geometrystring)
5010                 Mem_Free(geometrystring);
5011         if (fragmentstring)
5012                 Mem_Free(fragmentstring);
5013 }
5014
5015 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
5016 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
5017 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);}
5018 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);}
5019 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);}
5020 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);}
5021
5022 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
5023 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
5024 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);}
5025 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);}
5026 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);}
5027 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);}
5028
5029 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
5030 {
5031         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
5032         if (r_hlsl_permutation != perm)
5033         {
5034                 r_hlsl_permutation = perm;
5035                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
5036                 {
5037                         if (!r_hlsl_permutation->compiled)
5038                                 R_HLSL_CompilePermutation(perm, mode, permutation);
5039                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
5040                         {
5041                                 // remove features until we find a valid permutation
5042                                 int i;
5043                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5044                                 {
5045                                         // reduce i more quickly whenever it would not remove any bits
5046                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
5047                                         if (!(permutation & j))
5048                                                 continue;
5049                                         permutation -= j;
5050                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
5051                                         if (!r_hlsl_permutation->compiled)
5052                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
5053                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
5054                                                 break;
5055                                 }
5056                                 if (i >= SHADERPERMUTATION_COUNT)
5057                                 {
5058                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
5059                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
5060                                         return; // no bit left to clear, entire mode is broken
5061                                 }
5062                         }
5063                 }
5064                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
5065                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
5066         }
5067         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5068         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5069         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
5070 }
5071 #endif
5072
5073 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
5074 {
5075         DPSOFTRAST_SetShader(mode, permutation);
5076         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5077         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5078         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
5079 }
5080
5081 void R_GLSL_Restart_f(void)
5082 {
5083         unsigned int i, limit;
5084         if (glslshaderstring && glslshaderstring != builtinshaderstring && glslshaderstring != builtingles2shaderstring)
5085                 Mem_Free(glslshaderstring);
5086         glslshaderstring = NULL;
5087         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
5088                 Mem_Free(cgshaderstring);
5089         cgshaderstring = NULL;
5090         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
5091                 Mem_Free(hlslshaderstring);
5092         hlslshaderstring = NULL;
5093         switch(vid.renderpath)
5094         {
5095         case RENDERPATH_D3D9:
5096 #ifdef SUPPORTD3D
5097                 {
5098                         r_hlsl_permutation_t *p;
5099                         r_hlsl_permutation = NULL;
5100 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5101 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5102 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5103 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5104                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
5105                         for (i = 0;i < limit;i++)
5106                         {
5107                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
5108                                 {
5109                                         if (p->vertexshader)
5110                                                 IDirect3DVertexShader9_Release(p->vertexshader);
5111                                         if (p->pixelshader)
5112                                                 IDirect3DPixelShader9_Release(p->pixelshader);
5113                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
5114                                 }
5115                         }
5116                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
5117                 }
5118 #endif
5119                 break;
5120         case RENDERPATH_D3D10:
5121                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5122                 break;
5123         case RENDERPATH_D3D11:
5124                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5125                 break;
5126         case RENDERPATH_GL20:
5127         case RENDERPATH_GLES2:
5128                 {
5129                         r_glsl_permutation_t *p;
5130                         r_glsl_permutation = NULL;
5131                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5132                         for (i = 0;i < limit;i++)
5133                         {
5134                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5135                                 {
5136                                         GL_Backend_FreeProgram(p->program);
5137                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5138                                 }
5139                         }
5140                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5141                 }
5142                 break;
5143         case RENDERPATH_CGGL:
5144 #ifdef SUPPORTCG
5145                 {
5146                         r_cg_permutation_t *p;
5147                         r_cg_permutation = NULL;
5148                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5149                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5150                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5151                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5152                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5153                         for (i = 0;i < limit;i++)
5154                         {
5155                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5156                                 {
5157                                         if (p->vprogram)
5158                                                 cgDestroyProgram(p->vprogram);
5159                                         if (p->fprogram)
5160                                                 cgDestroyProgram(p->fprogram);
5161                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5162                                 }
5163                         }
5164                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5165                 }
5166 #endif
5167                 break;
5168         case RENDERPATH_GL13:
5169         case RENDERPATH_GL11:
5170                 break;
5171         case RENDERPATH_SOFT:
5172                 break;
5173         }
5174 }
5175
5176 void R_GLSL_DumpShader_f(void)
5177 {
5178         int i;
5179         qfile_t *file;
5180
5181         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5182         if (file)
5183         {
5184                 FS_Print(file, "/* The engine may define the following macros:\n");
5185                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5186                 for (i = 0;i < SHADERMODE_COUNT;i++)
5187                         FS_Print(file, glslshadermodeinfo[i].pretext);
5188                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5189                         FS_Print(file, shaderpermutationinfo[i].pretext);
5190                 FS_Print(file, "*/\n");
5191                 FS_Print(file, builtinshaderstring);
5192                 FS_Close(file);
5193                 Con_Printf("glsl/default.glsl written\n");
5194         }
5195         else
5196                 Con_Printf("failed to write to glsl/default.glsl\n");
5197
5198         file = FS_OpenRealFile("gles2/default.glsl", "w", false);
5199         if (file)
5200         {
5201                 FS_Print(file, "/* The engine may define the following macros:\n");
5202                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5203                 for (i = 0;i < SHADERMODE_COUNT;i++)
5204                         FS_Print(file, glslshadermodeinfo[i].pretext);
5205                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5206                         FS_Print(file, shaderpermutationinfo[i].pretext);
5207                 FS_Print(file, "*/\n");
5208                 FS_Print(file, builtingles2shaderstring);
5209                 FS_Close(file);
5210                 Con_Printf("gles2/default.glsl written\n");
5211         }
5212         else
5213                 Con_Printf("failed to write to glsl/default.glsl\n");
5214
5215 #ifdef SUPPORTCG
5216         file = FS_OpenRealFile("cg/default.cg", "w", false);
5217         if (file)
5218         {
5219                 FS_Print(file, "/* The engine may define the following macros:\n");
5220                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5221                 for (i = 0;i < SHADERMODE_COUNT;i++)
5222                         FS_Print(file, cgshadermodeinfo[i].pretext);
5223                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5224                         FS_Print(file, shaderpermutationinfo[i].pretext);
5225                 FS_Print(file, "*/\n");
5226                 FS_Print(file, builtincgshaderstring);
5227                 FS_Close(file);
5228                 Con_Printf("cg/default.cg written\n");
5229         }
5230         else
5231                 Con_Printf("failed to write to cg/default.cg\n");
5232 #endif
5233
5234         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5235         if (file)
5236         {
5237                 FS_Print(file, "/* The engine may define the following macros:\n");
5238                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5239                 for (i = 0;i < SHADERMODE_COUNT;i++)
5240                         FS_Print(file, hlslshadermodeinfo[i].pretext);
5241                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5242                         FS_Print(file, shaderpermutationinfo[i].pretext);
5243                 FS_Print(file, "*/\n");
5244                 FS_Print(file, builtincgshaderstring);
5245                 FS_Close(file);
5246                 Con_Printf("hlsl/default.hlsl written\n");
5247         }
5248         else
5249                 Con_Printf("failed to write to hlsl/default.hlsl\n");
5250 }
5251
5252 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5253 {
5254         if (!second)
5255                 texturemode = GL_MODULATE;
5256         switch (vid.renderpath)
5257         {
5258         case RENDERPATH_D3D9:
5259 #ifdef SUPPORTD3D
5260                 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))));
5261                 R_Mesh_TexBind(GL20TU_FIRST , first );
5262                 R_Mesh_TexBind(GL20TU_SECOND, second);
5263 #endif
5264                 break;
5265         case RENDERPATH_D3D10:
5266                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5267                 break;
5268         case RENDERPATH_D3D11:
5269                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5270                 break;
5271         case RENDERPATH_GL20:
5272         case RENDERPATH_GLES2:
5273                 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))));
5274                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
5275                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
5276                 break;
5277         case RENDERPATH_CGGL:
5278 #ifdef SUPPORTCG
5279                 CHECKCGERROR
5280                 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))));
5281                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5282                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5283 #endif
5284                 break;
5285         case RENDERPATH_GL13:
5286                 R_Mesh_TexBind(0, first );
5287                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5288                 R_Mesh_TexBind(1, second);
5289                 if (second)
5290                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5291                 break;
5292         case RENDERPATH_GL11:
5293                 R_Mesh_TexBind(0, first );
5294                 break;
5295         case RENDERPATH_SOFT:
5296                 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))));
5297                 R_Mesh_TexBind(GL20TU_FIRST , first );
5298                 R_Mesh_TexBind(GL20TU_SECOND, second);
5299                 break;
5300         }
5301 }
5302
5303 void R_SetupShader_DepthOrShadow(void)
5304 {
5305         switch (vid.renderpath)
5306         {
5307         case RENDERPATH_D3D9:
5308 #ifdef SUPPORTD3D
5309                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5310 #endif
5311                 break;
5312         case RENDERPATH_D3D10:
5313                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5314                 break;
5315         case RENDERPATH_D3D11:
5316                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5317                 break;
5318         case RENDERPATH_GL20:
5319         case RENDERPATH_GLES2:
5320                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5321                 break;
5322         case RENDERPATH_CGGL:
5323 #ifdef SUPPORTCG
5324                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5325 #endif
5326                 break;
5327         case RENDERPATH_GL13:
5328                 R_Mesh_TexBind(0, 0);
5329                 R_Mesh_TexBind(1, 0);
5330                 break;
5331         case RENDERPATH_GL11:
5332                 R_Mesh_TexBind(0, 0);
5333                 break;
5334         case RENDERPATH_SOFT:
5335                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
5336                 break;
5337         }
5338 }
5339
5340 void R_SetupShader_ShowDepth(void)
5341 {
5342         switch (vid.renderpath)
5343         {
5344         case RENDERPATH_D3D9:
5345 #ifdef SUPPORTHLSL
5346                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5347 #endif
5348                 break;
5349         case RENDERPATH_D3D10:
5350                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5351                 break;
5352         case RENDERPATH_D3D11:
5353                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5354                 break;
5355         case RENDERPATH_GL20:
5356         case RENDERPATH_GLES2:
5357                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5358                 break;
5359         case RENDERPATH_CGGL:
5360 #ifdef SUPPORTCG
5361                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5362 #endif
5363                 break;
5364         case RENDERPATH_GL13:
5365                 break;
5366         case RENDERPATH_GL11:
5367                 break;
5368         case RENDERPATH_SOFT:
5369                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
5370                 break;
5371         }
5372 }
5373
5374 extern qboolean r_shadow_usingdeferredprepass;
5375 extern cvar_t r_shadow_deferred_8bitrange;
5376 extern rtexture_t *r_shadow_attenuationgradienttexture;
5377 extern rtexture_t *r_shadow_attenuation2dtexture;
5378 extern rtexture_t *r_shadow_attenuation3dtexture;
5379 extern qboolean r_shadow_usingshadowmap2d;
5380 extern qboolean r_shadow_usingshadowmaportho;
5381 extern float r_shadow_shadowmap_texturescale[2];
5382 extern float r_shadow_shadowmap_parameters[4];
5383 extern qboolean r_shadow_shadowmapvsdct;
5384 extern qboolean r_shadow_shadowmapsampler;
5385 extern int r_shadow_shadowmappcf;
5386 extern rtexture_t *r_shadow_shadowmap2dtexture;
5387 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5388 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5389 extern matrix4x4_t r_shadow_shadowmapmatrix;
5390 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5391 extern int r_shadow_prepass_width;
5392 extern int r_shadow_prepass_height;
5393 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5394 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5395 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5396 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5397 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5398 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5399 {
5400         // a blendfunc allows colormod if:
5401         // a) it can never keep the destination pixel invariant, or
5402         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5403         // this is to prevent unintended side effects from colormod
5404
5405         // in formulas:
5406         // IF there is a (s, sa) for which for all (d, da),
5407         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5408         // THEN, for this (s, sa) and all (colormod, d, da):
5409         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5410         // OBVIOUSLY, this means that
5411         //   s*colormod * src(s*colormod, d, sa, da) = 0
5412         //   dst(s*colormod, d, sa, da)              = 1
5413
5414         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5415
5416         // main condition to leave dst color invariant:
5417         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5418         //   src == GL_ZERO:
5419         //     s * 0 + d * dst(s, d, sa, da) == d
5420         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5421         //       => colormod is a problem for GL_SRC_COLOR only
5422         //   src == GL_ONE:
5423         //     s + d * dst(s, d, sa, da) == d
5424         //       => s == 0
5425         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5426         //       => colormod is never problematic for these
5427         //   src == GL_SRC_COLOR:
5428         //     s*s + d * dst(s, d, sa, da) == d
5429         //       => s == 0
5430         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5431         //       => colormod is never problematic for these
5432         //   src == GL_ONE_MINUS_SRC_COLOR:
5433         //     s*(1-s) + d * dst(s, d, sa, da) == d
5434         //       => s == 0 or s == 1
5435         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5436         //       => colormod is a problem for GL_SRC_COLOR only
5437         //   src == GL_DST_COLOR
5438         //     s*d + d * dst(s, d, sa, da) == d
5439         //       => s == 1
5440         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5441         //       => colormod is always a problem
5442         //     or
5443         //       => s == 0
5444         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5445         //       => colormod is never problematic for these
5446         //       => BUT, we do not know s! We must assume it is problematic
5447         //       then... except in GL_ONE case, where we know all invariant
5448         //       cases are fine
5449         //   src == GL_ONE_MINUS_DST_COLOR
5450         //     s*(1-d) + d * dst(s, d, sa, da) == d
5451         //       => s == 0 (1-d is impossible to handle for our desired result)
5452         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5453         //       => colormod is never problematic for these
5454         //   src == GL_SRC_ALPHA
5455         //     s*sa + d * dst(s, d, sa, da) == d
5456         //       => s == 0, or sa == 0
5457         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5458         //       => colormod breaks in the case GL_SRC_COLOR only
5459         //   src == GL_ONE_MINUS_SRC_ALPHA
5460         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5461         //       => s == 0, or sa == 1
5462         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5463         //       => colormod breaks in the case GL_SRC_COLOR only
5464         //   src == GL_DST_ALPHA
5465         //     s*da + d * dst(s, d, sa, da) == d
5466         //       => s == 0
5467         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5468         //       => colormod is never problematic for these
5469
5470         switch(src)
5471         {
5472                 case GL_ZERO:
5473                 case GL_ONE_MINUS_SRC_COLOR:
5474                 case GL_SRC_ALPHA:
5475                 case GL_ONE_MINUS_SRC_ALPHA:
5476                         if(dst == GL_SRC_COLOR)
5477                                 return false;
5478                         return true;
5479                 case GL_ONE:
5480                 case GL_SRC_COLOR:
5481                 case GL_ONE_MINUS_DST_COLOR:
5482                 case GL_DST_ALPHA:
5483                 case GL_ONE_MINUS_DST_ALPHA:
5484                         return true;
5485                 case GL_DST_COLOR:
5486                         if(dst == GL_ONE)
5487                                 return true;
5488                         return false;
5489                 default:
5490                         return false;
5491         }
5492 }
5493 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)
5494 {
5495         // select a permutation of the lighting shader appropriate to this
5496         // combination of texture, entity, light source, and fogging, only use the
5497         // minimum features necessary to avoid wasting rendering time in the
5498         // fragment shader on features that are not being used
5499         unsigned int permutation = 0;
5500         unsigned int mode = 0;
5501         qboolean allow_colormod;
5502         static float dummy_colormod[3] = {1, 1, 1};
5503         float *colormod = rsurface.colormod;
5504         float m16f[16];
5505         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5506         if (rsurfacepass == RSURFPASS_BACKGROUND)
5507         {
5508                 // distorted background
5509                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5510                 {
5511                         mode = SHADERMODE_WATER;
5512                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5513                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5514                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
5515                         {
5516                                 // this is the right thing to do for wateralpha
5517                                 GL_BlendFunc(GL_ONE, GL_ZERO);
5518                                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5519                         }
5520                         else
5521                         {
5522                                 // this is the right thing to do for entity alpha
5523                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5524                                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5525                         }
5526                 }
5527                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5528                 {
5529                         mode = SHADERMODE_REFRACTION;
5530                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5531                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5532                 }
5533                 else
5534                 {
5535                         mode = SHADERMODE_GENERIC;
5536                         permutation |= SHADERPERMUTATION_DIFFUSE;
5537                         GL_BlendFunc(GL_ONE, GL_ZERO);
5538                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5539                 }
5540                 GL_AlphaTest(false);
5541         }
5542         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5543         {
5544                 if (r_glsl_offsetmapping.integer)
5545                 {
5546                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5547                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5548                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5549                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5550                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5551                         {
5552                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5553                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5554                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5555                         }
5556                 }
5557                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5558                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5559                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5560                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5561                 // normalmap (deferred prepass), may use alpha test on diffuse
5562                 mode = SHADERMODE_DEFERREDGEOMETRY;
5563                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5564                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5565                 GL_AlphaTest(false);
5566                 GL_BlendFunc(GL_ONE, GL_ZERO);
5567                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5568         }
5569         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5570         {
5571                 if (r_glsl_offsetmapping.integer)
5572                 {
5573                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5574                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5575                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5576                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5577                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5578                         {
5579                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5580                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5581                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5582                         }
5583                 }
5584                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5585                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5586                 // light source
5587                 mode = SHADERMODE_LIGHTSOURCE;
5588                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5589                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5590                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5591                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5592                 if (diffusescale > 0)
5593                         permutation |= SHADERPERMUTATION_DIFFUSE;
5594                 if (specularscale > 0)
5595                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5596                 if (r_refdef.fogenabled)
5597                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5598                 if (rsurface.texture->colormapping)
5599                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5600                 if (r_shadow_usingshadowmap2d)
5601                 {
5602                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5603                         if(r_shadow_shadowmapvsdct)
5604                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5605
5606                         if (r_shadow_shadowmapsampler)
5607                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5608                         if (r_shadow_shadowmappcf > 1)
5609                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5610                         else if (r_shadow_shadowmappcf)
5611                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5612                 }
5613                 if (rsurface.texture->reflectmasktexture)
5614                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5615                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5616                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5617                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5618         }
5619         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5620         {
5621                 if (r_glsl_offsetmapping.integer)
5622                 {
5623                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5624                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5625                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5626                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5627                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5628                         {
5629                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5630                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5631                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5632                         }
5633                 }
5634                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5635                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5636                 // unshaded geometry (fullbright or ambient model lighting)
5637                 mode = SHADERMODE_FLATCOLOR;
5638                 ambientscale = diffusescale = specularscale = 0;
5639                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5640                         permutation |= SHADERPERMUTATION_GLOW;
5641                 if (r_refdef.fogenabled)
5642                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5643                 if (rsurface.texture->colormapping)
5644                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5645                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5646                 {
5647                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5648                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5649
5650                         if (r_shadow_shadowmapsampler)
5651                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5652                         if (r_shadow_shadowmappcf > 1)
5653                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5654                         else if (r_shadow_shadowmappcf)
5655                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5656                 }
5657                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5658                         permutation |= SHADERPERMUTATION_REFLECTION;
5659                 if (rsurface.texture->reflectmasktexture)
5660                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5661                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5662                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5663                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5664         }
5665         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5666         {
5667                 if (r_glsl_offsetmapping.integer)
5668                 {
5669                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5670                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5671                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5672                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5673                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5674                         {
5675                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5676                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5677                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5678                         }
5679                 }
5680                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5681                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5682                 // directional model lighting
5683                 mode = SHADERMODE_LIGHTDIRECTION;
5684                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5685                         permutation |= SHADERPERMUTATION_GLOW;
5686                 permutation |= SHADERPERMUTATION_DIFFUSE;
5687                 if (specularscale > 0)
5688                         permutation |= SHADERPERMUTATION_SPECULAR;
5689                 if (r_refdef.fogenabled)
5690                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5691                 if (rsurface.texture->colormapping)
5692                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5693                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5694                 {
5695                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5696                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5697
5698                         if (r_shadow_shadowmapsampler)
5699                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5700                         if (r_shadow_shadowmappcf > 1)
5701                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5702                         else if (r_shadow_shadowmappcf)
5703                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5704                 }
5705                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5706                         permutation |= SHADERPERMUTATION_REFLECTION;
5707                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5708                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5709                 if (rsurface.texture->reflectmasktexture)
5710                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5711                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5712                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5713                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5714         }
5715         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5716         {
5717                 if (r_glsl_offsetmapping.integer)
5718                 {
5719                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5720                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5721                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5722                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5723                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5724                         {
5725                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5726                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5727                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5728                         }
5729                 }
5730                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5731                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5732                 // ambient model lighting
5733                 mode = SHADERMODE_LIGHTDIRECTION;
5734                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5735                         permutation |= SHADERPERMUTATION_GLOW;
5736                 if (r_refdef.fogenabled)
5737                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5738                 if (rsurface.texture->colormapping)
5739                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5740                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5741                 {
5742                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5743                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5744
5745                         if (r_shadow_shadowmapsampler)
5746                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5747                         if (r_shadow_shadowmappcf > 1)
5748                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5749                         else if (r_shadow_shadowmappcf)
5750                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5751                 }
5752                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5753                         permutation |= SHADERPERMUTATION_REFLECTION;
5754                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5755                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5756                 if (rsurface.texture->reflectmasktexture)
5757                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5758                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5759                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5760                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5761         }
5762         else
5763         {
5764                 if (r_glsl_offsetmapping.integer)
5765                 {
5766                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5767                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5768                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5769                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5770                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5771                         {
5772                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5773                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5774                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5775                         }
5776                 }
5777                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5778                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5779                 // lightmapped wall
5780                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5781                         permutation |= SHADERPERMUTATION_GLOW;
5782                 if (r_refdef.fogenabled)
5783                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5784                 if (rsurface.texture->colormapping)
5785                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5786                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5787                 {
5788                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5789                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5790
5791                         if (r_shadow_shadowmapsampler)
5792                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5793                         if (r_shadow_shadowmappcf > 1)
5794                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5795                         else if (r_shadow_shadowmappcf)
5796                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5797                 }
5798                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5799                         permutation |= SHADERPERMUTATION_REFLECTION;
5800                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5801                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5802                 if (rsurface.texture->reflectmasktexture)
5803                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5804                 if (FAKELIGHT_ENABLED)
5805                 {
5806                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5807                         mode = SHADERMODE_FAKELIGHT;
5808                         permutation |= SHADERPERMUTATION_DIFFUSE;
5809                         if (specularscale > 0)
5810                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5811                 }
5812                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5813                 {
5814                         // deluxemapping (light direction texture)
5815                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5816                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5817                         else
5818                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5819                         permutation |= SHADERPERMUTATION_DIFFUSE;
5820                         if (specularscale > 0)
5821                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5822                 }
5823                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5824                 {
5825                         // fake deluxemapping (uniform light direction in tangentspace)
5826                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5827                         permutation |= SHADERPERMUTATION_DIFFUSE;
5828                         if (specularscale > 0)
5829                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5830                 }
5831                 else if (rsurface.uselightmaptexture)
5832                 {
5833                         // ordinary lightmapping (q1bsp, q3bsp)
5834                         mode = SHADERMODE_LIGHTMAP;
5835                 }
5836                 else
5837                 {
5838                         // ordinary vertex coloring (q3bsp)
5839                         mode = SHADERMODE_VERTEXCOLOR;
5840                 }
5841                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5842                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5843                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5844         }
5845         if(!allow_colormod)
5846                 colormod = dummy_colormod;
5847         switch(vid.renderpath)
5848         {
5849         case RENDERPATH_D3D9:
5850 #ifdef SUPPORTD3D
5851                 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);
5852                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5853                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5854                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5855                 if (mode == SHADERMODE_LIGHTSOURCE)
5856                 {
5857                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5858                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5859                 }
5860                 else
5861                 {
5862                         if (mode == SHADERMODE_LIGHTDIRECTION)
5863                         {
5864                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5865                         }
5866                 }
5867                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5868                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5869                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5870                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5871                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5872
5873                 if (mode == SHADERMODE_LIGHTSOURCE)
5874                 {
5875                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5876                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5877                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5878                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5879                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5880
5881                         // additive passes are only darkened by fog, not tinted
5882                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5883                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5884                 }
5885                 else
5886                 {
5887                         if (mode == SHADERMODE_FLATCOLOR)
5888                         {
5889                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5890                         }
5891                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5892                         {
5893                                 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]);
5894                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5895                                 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);
5896                                 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);
5897                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5898                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5899                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5900                         }
5901                         else
5902                         {
5903                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5904                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5905                                 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);
5906                                 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);
5907                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5908                         }
5909                         // additive passes are only darkened by fog, not tinted
5910                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5911                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5912                         else
5913                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5914                         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);
5915                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5916                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5917                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5918                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5919                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5920                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5921                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5922                         if (mode == SHADERMODE_WATER)
5923                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5924                 }
5925                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5926                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5927                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5928                 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));
5929                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5930                 if (rsurface.texture->pantstexture)
5931                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5932                 else
5933                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5934                 if (rsurface.texture->shirttexture)
5935                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5936                 else
5937                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5938                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5939                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5940                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5941                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5942                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5943                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5944                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5945
5946                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5947                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5948                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5949                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5950                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5951                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5952                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5953                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5954                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5955                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5956                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5957                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5958                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5959                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5960                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5961                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5962                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5963                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5964                 {
5965                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5966                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5967                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5968                 }
5969                 else
5970                 {
5971                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5972                 }
5973 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5974 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5975                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5976                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5977                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5978                 {
5979                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5980                         if (rsurface.rtlight)
5981                         {
5982                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5983                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5984                         }
5985                 }
5986 #endif
5987                 break;
5988         case RENDERPATH_D3D10:
5989                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5990                 break;
5991         case RENDERPATH_D3D11:
5992                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5993                 break;
5994         case RENDERPATH_GL20:
5995         case RENDERPATH_GLES2:
5996                 if (!vid.useinterleavedarrays)
5997                 {
5998                         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);
5999                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
6000                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
6001                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
6002                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
6003                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6004                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6005                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6006                 }
6007                 else
6008                 {
6009                         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);
6010                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6011                 }
6012                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6013                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
6014                 if (mode == SHADERMODE_LIGHTSOURCE)
6015                 {
6016                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
6017                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
6018                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
6019                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
6020                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
6021                         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);
6022         
6023                         // additive passes are only darkened by fog, not tinted
6024                         if (r_glsl_permutation->loc_FogColor >= 0)
6025                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
6026                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6027                 }
6028                 else
6029                 {
6030                         if (mode == SHADERMODE_FLATCOLOR)
6031                         {
6032                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
6033                         }
6034                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6035                         {
6036                                 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]);
6037                                 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]);
6038                                 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);
6039                                 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);
6040                                 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);
6041                                 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]);
6042                                 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]);
6043                         }
6044                         else
6045                         {
6046                                 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]);
6047                                 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]);
6048                                 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);
6049                                 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);
6050                                 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);
6051                         }
6052                         // additive passes are only darkened by fog, not tinted
6053                         if (r_glsl_permutation->loc_FogColor >= 0)
6054                         {
6055                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6056                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
6057                                 else
6058                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6059                         }
6060                         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);
6061                         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]);
6062                         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]);
6063                         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]);
6064                         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]);
6065                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
6066                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
6067                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6068                         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]);
6069                 }
6070                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
6071                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
6072                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
6073                 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]);
6074                 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]);
6075
6076                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
6077                 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));
6078                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
6079                 if (r_glsl_permutation->loc_Color_Pants >= 0)
6080                 {
6081                         if (rsurface.texture->pantstexture)
6082                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6083                         else
6084                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
6085                 }
6086                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
6087                 {
6088                         if (rsurface.texture->shirttexture)
6089                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6090                         else
6091                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
6092                 }
6093                 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]);
6094                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
6095                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
6096                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
6097                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
6098                 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]);
6099                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6100
6101                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
6102                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
6103                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
6104                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
6105                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
6106                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
6107                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
6108                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
6109                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
6110                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
6111                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
6112                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
6113                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
6114                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
6115                 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);
6116                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
6117                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
6118                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
6119                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
6120                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
6121                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6122                 {
6123                         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);
6124                         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);
6125                         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);
6126                 }
6127                 else
6128                 {
6129                         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);
6130                 }
6131                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
6132                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
6133                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
6134                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
6135                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6136                 {
6137                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
6138                         if (rsurface.rtlight)
6139                         {
6140                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
6141                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
6142                         }
6143                 }
6144                 CHECKGLERROR
6145                 break;
6146         case RENDERPATH_CGGL:
6147 #ifdef SUPPORTCG
6148                 if (!vid.useinterleavedarrays)
6149                 {
6150                         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);
6151                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
6152                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
6153                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
6154                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
6155                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6156                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6157                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6158                 }
6159                 else
6160                 {
6161                         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);
6162                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6163                 }
6164                 R_SetupShader_SetPermutationCG(mode, permutation);
6165                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6166                 if (mode == SHADERMODE_LIGHTSOURCE)
6167                 {
6168                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6169                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6170                 }
6171                 else
6172                 {
6173                         if (mode == SHADERMODE_LIGHTDIRECTION)
6174                         {
6175                                 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
6176                         }
6177                 }
6178                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6179                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6180                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6181                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6182                 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
6183                 CHECKGLERROR
6184
6185                 if (mode == SHADERMODE_LIGHTSOURCE)
6186                 {
6187                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6188                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6189                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6190                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6191                         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
6192
6193                         // additive passes are only darkened by fog, not tinted
6194                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6195                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6196                 }
6197                 else
6198                 {
6199                         if (mode == SHADERMODE_FLATCOLOR)
6200                         {
6201                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6202                         }
6203                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6204                         {
6205                                 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
6206                                 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
6207                                 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
6208                                 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
6209                                 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
6210                                 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
6211                                 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
6212                         }
6213                         else
6214                         {
6215                                 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
6216                                 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
6217                                 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
6218                                 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
6219                                 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
6220                         }
6221                         // additive passes are only darkened by fog, not tinted
6222                         if (r_cg_permutation->fp_FogColor)
6223                         {
6224                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6225                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6226                                 else
6227                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6228                                 CHECKCGERROR
6229                         }
6230                         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
6231                         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
6232                         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
6233                         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
6234                         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
6235                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6236                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6237                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6238                         if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6239                 }
6240                 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
6241                 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
6242                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6243                 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
6244                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6245                 if (r_cg_permutation->fp_Color_Pants)
6246                 {
6247                         if (rsurface.texture->pantstexture)
6248                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6249                         else
6250                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6251                         CHECKCGERROR
6252                 }
6253                 if (r_cg_permutation->fp_Color_Shirt)
6254                 {
6255                         if (rsurface.texture->shirttexture)
6256                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6257                         else
6258                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6259                         CHECKCGERROR
6260                 }
6261                 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
6262                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6263                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6264                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6265                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6266                 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
6267                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6268
6269         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
6270         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
6271         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
6272                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
6273                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
6274                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
6275                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
6276                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
6277                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
6278                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
6279                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
6280                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
6281                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
6282                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
6283                 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
6284                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
6285                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
6286                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6287                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6288                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6289                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6290                 {
6291                         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
6292                         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
6293                         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
6294                 }
6295                 else
6296                 {
6297                         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
6298                 }
6299                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6300                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6301                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6302                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6303                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6304                 {
6305                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6306                         if (rsurface.rtlight)
6307                         {
6308                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6309                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6310                         }
6311                 }
6312
6313                 CHECKGLERROR
6314 #endif
6315                 break;
6316         case RENDERPATH_GL13:
6317         case RENDERPATH_GL11:
6318                 break;
6319         case RENDERPATH_SOFT:
6320                 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);
6321                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
6322                 R_SetupShader_SetPermutationSoft(mode, permutation);
6323                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
6324                 if (mode == SHADERMODE_LIGHTSOURCE)
6325                 {
6326                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
6327                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
6328                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
6329                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
6330                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
6331                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
6332         
6333                         // additive passes are only darkened by fog, not tinted
6334                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
6335                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6336                 }
6337                 else
6338                 {
6339                         if (mode == SHADERMODE_FLATCOLOR)
6340                         {
6341                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
6342                         }
6343                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6344                         {
6345                                 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]);
6346                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
6347                                 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);
6348                                 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);
6349                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
6350                                 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]);
6351                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
6352                         }
6353                         else
6354                         {
6355                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
6356                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
6357                                 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);
6358                                 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);
6359                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
6360                         }
6361                         // additive passes are only darkened by fog, not tinted
6362                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6363                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
6364                         else
6365                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6366                         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);
6367                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
6368                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
6369                         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]);
6370                         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]);
6371                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
6372                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
6373                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6374                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6375                 }
6376                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
6377                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
6378                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
6379                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6380                 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]);
6381
6382                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
6383                 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));
6384                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
6385                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
6386                 {
6387                         if (rsurface.texture->pantstexture)
6388                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6389                         else
6390                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
6391                 }
6392                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
6393                 {
6394                         if (rsurface.texture->shirttexture)
6395                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6396                         else
6397                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
6398                 }
6399                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
6400                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
6401                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
6402                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
6403                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
6404                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6405                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6406
6407                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
6408                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
6409                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
6410                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
6411                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
6412                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
6413                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
6414                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
6415                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
6416                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
6417                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
6418                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
6419                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
6420                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
6421                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
6422                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
6423                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
6424                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6425                 {
6426                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
6427                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
6428                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6429                 }
6430                 else
6431                 {
6432                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6433                 }
6434 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
6435 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
6436                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
6437                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
6438                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6439                 {
6440                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
6441                         if (rsurface.rtlight)
6442                         {
6443                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
6444                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
6445                         }
6446                 }
6447                 break;
6448         }
6449 }
6450
6451 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6452 {
6453         // select a permutation of the lighting shader appropriate to this
6454         // combination of texture, entity, light source, and fogging, only use the
6455         // minimum features necessary to avoid wasting rendering time in the
6456         // fragment shader on features that are not being used
6457         unsigned int permutation = 0;
6458         unsigned int mode = 0;
6459         const float *lightcolorbase = rtlight->currentcolor;
6460         float ambientscale = rtlight->ambientscale;
6461         float diffusescale = rtlight->diffusescale;
6462         float specularscale = rtlight->specularscale;
6463         // this is the location of the light in view space
6464         vec3_t viewlightorigin;
6465         // this transforms from view space (camera) to light space (cubemap)
6466         matrix4x4_t viewtolight;
6467         matrix4x4_t lighttoview;
6468         float viewtolight16f[16];
6469         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6470         // light source
6471         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6472         if (rtlight->currentcubemap != r_texture_whitecube)
6473                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6474         if (diffusescale > 0)
6475                 permutation |= SHADERPERMUTATION_DIFFUSE;
6476         if (specularscale > 0)
6477                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6478         if (r_shadow_usingshadowmap2d)
6479         {
6480                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6481                 if (r_shadow_shadowmapvsdct)
6482                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6483
6484                 if (r_shadow_shadowmapsampler)
6485                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6486                 if (r_shadow_shadowmappcf > 1)
6487                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6488                 else if (r_shadow_shadowmappcf)
6489                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6490         }
6491         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6492         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6493         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6494         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6495         switch(vid.renderpath)
6496         {
6497         case RENDERPATH_D3D9:
6498 #ifdef SUPPORTD3D
6499                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6500                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6501                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6502                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6503                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6504                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6505                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6506                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6507                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6508                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6509                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6510
6511                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6512                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
6513                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6514                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6515                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
6516                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6517 #endif
6518                 break;
6519         case RENDERPATH_D3D10:
6520                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6521                 break;
6522         case RENDERPATH_D3D11:
6523                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6524                 break;
6525         case RENDERPATH_GL20:
6526         case RENDERPATH_GLES2:
6527                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6528                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6529                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6530                 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);
6531                 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);
6532                 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);
6533                 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]);
6534                 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]);
6535                 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));
6536                 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]);
6537                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
6538
6539                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
6540                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
6541                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
6542                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
6543                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
6544                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
6545                 break;
6546         case RENDERPATH_CGGL:
6547 #ifdef SUPPORTCG
6548                 R_SetupShader_SetPermutationCG(mode, permutation);
6549                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6550                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6551                 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
6552                 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
6553                 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
6554                 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
6555                 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
6556                 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
6557                 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
6558                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6559
6560                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6561                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6562                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6563                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6564                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6565                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6566 #endif
6567                 break;
6568         case RENDERPATH_GL13:
6569         case RENDERPATH_GL11:
6570                 break;
6571         case RENDERPATH_SOFT:
6572                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6573                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6574                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
6575                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6576                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6577                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6578                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6579                 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]);
6580                 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));
6581                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6582                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6583
6584                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6585                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6586                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6587                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6588                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6589                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6590                 break;
6591         }
6592 }
6593
6594 #define SKINFRAME_HASH 1024
6595
6596 typedef struct
6597 {
6598         int loadsequence; // incremented each level change
6599         memexpandablearray_t array;
6600         skinframe_t *hash[SKINFRAME_HASH];
6601 }
6602 r_skinframe_t;
6603 r_skinframe_t r_skinframe;
6604
6605 void R_SkinFrame_PrepareForPurge(void)
6606 {
6607         r_skinframe.loadsequence++;
6608         // wrap it without hitting zero
6609         if (r_skinframe.loadsequence >= 200)
6610                 r_skinframe.loadsequence = 1;
6611 }
6612
6613 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6614 {
6615         if (!skinframe)
6616                 return;
6617         // mark the skinframe as used for the purging code
6618         skinframe->loadsequence = r_skinframe.loadsequence;
6619 }
6620
6621 void R_SkinFrame_Purge(void)
6622 {
6623         int i;
6624         skinframe_t *s;
6625         for (i = 0;i < SKINFRAME_HASH;i++)
6626         {
6627                 for (s = r_skinframe.hash[i];s;s = s->next)
6628                 {
6629                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6630                         {
6631                                 if (s->merged == s->base)
6632                                         s->merged = NULL;
6633                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6634                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6635                                 R_PurgeTexture(s->merged);s->merged = NULL;
6636                                 R_PurgeTexture(s->base  );s->base   = NULL;
6637                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6638                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6639                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6640                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6641                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6642                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6643                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6644                                 s->loadsequence = 0;
6645                         }
6646                 }
6647         }
6648 }
6649
6650 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6651         skinframe_t *item;
6652         char basename[MAX_QPATH];
6653
6654         Image_StripImageExtension(name, basename, sizeof(basename));
6655
6656         if( last == NULL ) {
6657                 int hashindex;
6658                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6659                 item = r_skinframe.hash[hashindex];
6660         } else {
6661                 item = last->next;
6662         }
6663
6664         // linearly search through the hash bucket
6665         for( ; item ; item = item->next ) {
6666                 if( !strcmp( item->basename, basename ) ) {
6667                         return item;
6668                 }
6669         }
6670         return NULL;
6671 }
6672
6673 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6674 {
6675         skinframe_t *item;
6676         int hashindex;
6677         char basename[MAX_QPATH];
6678
6679         Image_StripImageExtension(name, basename, sizeof(basename));
6680
6681         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6682         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6683                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6684                         break;
6685
6686         if (!item) {
6687                 rtexture_t *dyntexture;
6688                 // check whether its a dynamic texture
6689                 dyntexture = CL_GetDynTexture( basename );
6690                 if (!add && !dyntexture)
6691                         return NULL;
6692                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6693                 memset(item, 0, sizeof(*item));
6694                 strlcpy(item->basename, basename, sizeof(item->basename));
6695                 item->base = dyntexture; // either NULL or dyntexture handle
6696                 item->textureflags = textureflags;
6697                 item->comparewidth = comparewidth;
6698                 item->compareheight = compareheight;
6699                 item->comparecrc = comparecrc;
6700                 item->next = r_skinframe.hash[hashindex];
6701                 r_skinframe.hash[hashindex] = item;
6702         }
6703         else if( item->base == NULL )
6704         {
6705                 rtexture_t *dyntexture;
6706                 // check whether its a dynamic texture
6707                 // 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]
6708                 dyntexture = CL_GetDynTexture( basename );
6709                 item->base = dyntexture; // either NULL or dyntexture handle
6710         }
6711
6712         R_SkinFrame_MarkUsed(item);
6713         return item;
6714 }
6715
6716 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6717         { \
6718                 unsigned long long avgcolor[5], wsum; \
6719                 int pix, comp, w; \
6720                 avgcolor[0] = 0; \
6721                 avgcolor[1] = 0; \
6722                 avgcolor[2] = 0; \
6723                 avgcolor[3] = 0; \
6724                 avgcolor[4] = 0; \
6725                 wsum = 0; \
6726                 for(pix = 0; pix < cnt; ++pix) \
6727                 { \
6728                         w = 0; \
6729                         for(comp = 0; comp < 3; ++comp) \
6730                                 w += getpixel; \
6731                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6732                         { \
6733                                 ++wsum; \
6734                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6735                                 w = getpixel; \
6736                                 for(comp = 0; comp < 3; ++comp) \
6737                                         avgcolor[comp] += getpixel * w; \
6738                                 avgcolor[3] += w; \
6739                         } \
6740                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6741                         avgcolor[4] += getpixel; \
6742                 } \
6743                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6744                         avgcolor[3] = 1; \
6745                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6746                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6747                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6748                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6749         }
6750
6751 extern cvar_t gl_picmip;
6752 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6753 {
6754         int j;
6755         unsigned char *pixels;
6756         unsigned char *bumppixels;
6757         unsigned char *basepixels = NULL;
6758         int basepixels_width = 0;
6759         int basepixels_height = 0;
6760         skinframe_t *skinframe;
6761         rtexture_t *ddsbase = NULL;
6762         qboolean ddshasalpha = false;
6763         float ddsavgcolor[4];
6764         char basename[MAX_QPATH];
6765         int miplevel = R_PicmipForFlags(textureflags);
6766         int savemiplevel = miplevel;
6767         int mymiplevel;
6768
6769         if (cls.state == ca_dedicated)
6770                 return NULL;
6771
6772         // return an existing skinframe if already loaded
6773         // if loading of the first image fails, don't make a new skinframe as it
6774         // would cause all future lookups of this to be missing
6775         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6776         if (skinframe && skinframe->base)
6777                 return skinframe;
6778
6779         Image_StripImageExtension(name, basename, sizeof(basename));
6780
6781         // check for DDS texture file first
6782         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6783         {
6784                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6785                 if (basepixels == NULL)
6786                         return NULL;
6787         }
6788
6789         // FIXME handle miplevel
6790
6791         if (developer_loading.integer)
6792                 Con_Printf("loading skin \"%s\"\n", name);
6793
6794         // we've got some pixels to store, so really allocate this new texture now
6795         if (!skinframe)
6796                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6797         skinframe->stain = NULL;
6798         skinframe->merged = NULL;
6799         skinframe->base = NULL;
6800         skinframe->pants = NULL;
6801         skinframe->shirt = NULL;
6802         skinframe->nmap = NULL;
6803         skinframe->gloss = NULL;
6804         skinframe->glow = NULL;
6805         skinframe->fog = NULL;
6806         skinframe->reflect = NULL;
6807         skinframe->hasalpha = false;
6808
6809         if (ddsbase)
6810         {
6811                 skinframe->base = ddsbase;
6812                 skinframe->hasalpha = ddshasalpha;
6813                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6814                 if (r_loadfog && skinframe->hasalpha)
6815                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6816                 //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]);
6817         }
6818         else
6819         {
6820                 basepixels_width = image_width;
6821                 basepixels_height = image_height;
6822                 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);
6823                 if (textureflags & TEXF_ALPHA)
6824                 {
6825                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6826                         {
6827                                 if (basepixels[j] < 255)
6828                                 {
6829                                         skinframe->hasalpha = true;
6830                                         break;
6831                                 }
6832                         }
6833                         if (r_loadfog && skinframe->hasalpha)
6834                         {
6835                                 // has transparent pixels
6836                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6837                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6838                                 {
6839                                         pixels[j+0] = 255;
6840                                         pixels[j+1] = 255;
6841                                         pixels[j+2] = 255;
6842                                         pixels[j+3] = basepixels[j+3];
6843                                 }
6844                                 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);
6845                                 Mem_Free(pixels);
6846                         }
6847                 }
6848                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6849                 //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]);
6850                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6851                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6852                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6853                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6854         }
6855
6856         if (r_loaddds)
6857         {
6858                 mymiplevel = savemiplevel;
6859                 if (r_loadnormalmap)
6860                         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);
6861                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6862                 if (r_loadgloss)
6863                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6864                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6865                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6866                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6867         }
6868
6869         // _norm is the name used by tenebrae and has been adopted as standard
6870         if (r_loadnormalmap && skinframe->nmap == NULL)
6871         {
6872                 mymiplevel = savemiplevel;
6873                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6874                 {
6875                         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);
6876                         Mem_Free(pixels);
6877                         pixels = NULL;
6878                 }
6879                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6880                 {
6881                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6882                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6883                         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);
6884                         Mem_Free(pixels);
6885                         Mem_Free(bumppixels);
6886                 }
6887                 else if (r_shadow_bumpscale_basetexture.value > 0)
6888                 {
6889                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6890                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6891                         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);
6892                         Mem_Free(pixels);
6893                 }
6894                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6895                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6896         }
6897
6898         // _luma is supported only for tenebrae compatibility
6899         // _glow is the preferred name
6900         mymiplevel = savemiplevel;
6901         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))))
6902         {
6903                 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);
6904                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6905                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6906                 Mem_Free(pixels);pixels = NULL;
6907         }
6908
6909         mymiplevel = savemiplevel;
6910         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6911         {
6912                 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);
6913                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6914                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6915                 Mem_Free(pixels);
6916                 pixels = NULL;
6917         }
6918
6919         mymiplevel = savemiplevel;
6920         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6921         {
6922                 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);
6923                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6924                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6925                 Mem_Free(pixels);
6926                 pixels = NULL;
6927         }
6928
6929         mymiplevel = savemiplevel;
6930         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6931         {
6932                 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);
6933                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6934                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6935                 Mem_Free(pixels);
6936                 pixels = NULL;
6937         }
6938
6939         mymiplevel = savemiplevel;
6940         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6941         {
6942                 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);
6943                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6944                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6945                 Mem_Free(pixels);
6946                 pixels = NULL;
6947         }
6948
6949         if (basepixels)
6950                 Mem_Free(basepixels);
6951
6952         return skinframe;
6953 }
6954
6955 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6956 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6957 {
6958         int i;
6959         unsigned char *temp1, *temp2;
6960         skinframe_t *skinframe;
6961
6962         if (cls.state == ca_dedicated)
6963                 return NULL;
6964
6965         // if already loaded just return it, otherwise make a new skinframe
6966         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6967         if (skinframe && skinframe->base)
6968                 return skinframe;
6969
6970         skinframe->stain = NULL;
6971         skinframe->merged = NULL;
6972         skinframe->base = NULL;
6973         skinframe->pants = NULL;
6974         skinframe->shirt = NULL;
6975         skinframe->nmap = NULL;
6976         skinframe->gloss = NULL;
6977         skinframe->glow = NULL;
6978         skinframe->fog = NULL;
6979         skinframe->reflect = NULL;
6980         skinframe->hasalpha = false;
6981
6982         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6983         if (!skindata)
6984                 return NULL;
6985
6986         if (developer_loading.integer)
6987                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6988
6989         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6990         {
6991                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6992                 temp2 = temp1 + width * height * 4;
6993                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6994                 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);
6995                 Mem_Free(temp1);
6996         }
6997         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6998         if (textureflags & TEXF_ALPHA)
6999         {
7000                 for (i = 3;i < width * height * 4;i += 4)
7001                 {
7002                         if (skindata[i] < 255)
7003                         {
7004                                 skinframe->hasalpha = true;
7005                                 break;
7006                         }
7007                 }
7008                 if (r_loadfog && skinframe->hasalpha)
7009                 {
7010                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
7011                         memcpy(fogpixels, skindata, width * height * 4);
7012                         for (i = 0;i < width * height * 4;i += 4)
7013                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
7014                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
7015                         Mem_Free(fogpixels);
7016                 }
7017         }
7018
7019         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
7020         //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]);
7021
7022         return skinframe;
7023 }
7024
7025 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
7026 {
7027         int i;
7028         int featuresmask;
7029         skinframe_t *skinframe;
7030
7031         if (cls.state == ca_dedicated)
7032                 return NULL;
7033
7034         // if already loaded just return it, otherwise make a new skinframe
7035         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
7036         if (skinframe && skinframe->base)
7037                 return skinframe;
7038
7039         skinframe->stain = NULL;
7040         skinframe->merged = NULL;
7041         skinframe->base = NULL;
7042         skinframe->pants = NULL;
7043         skinframe->shirt = NULL;
7044         skinframe->nmap = NULL;
7045         skinframe->gloss = NULL;
7046         skinframe->glow = NULL;
7047         skinframe->fog = NULL;
7048         skinframe->reflect = NULL;
7049         skinframe->hasalpha = false;
7050
7051         // if no data was provided, then clearly the caller wanted to get a blank skinframe
7052         if (!skindata)
7053                 return NULL;
7054
7055         if (developer_loading.integer)
7056                 Con_Printf("loading quake skin \"%s\"\n", name);
7057
7058         // 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)
7059         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
7060         memcpy(skinframe->qpixels, skindata, width*height);
7061         skinframe->qwidth = width;
7062         skinframe->qheight = height;
7063
7064         featuresmask = 0;
7065         for (i = 0;i < width * height;i++)
7066                 featuresmask |= palette_featureflags[skindata[i]];
7067
7068         skinframe->hasalpha = false;
7069         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
7070         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
7071         skinframe->qgeneratemerged = true;
7072         skinframe->qgeneratebase = skinframe->qhascolormapping;
7073         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
7074
7075         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
7076         //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]);
7077
7078         return skinframe;
7079 }
7080
7081 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
7082 {
7083         int width;
7084         int height;
7085         unsigned char *skindata;
7086
7087         if (!skinframe->qpixels)
7088                 return;
7089
7090         if (!skinframe->qhascolormapping)
7091                 colormapped = false;
7092
7093         if (colormapped)
7094         {
7095                 if (!skinframe->qgeneratebase)
7096                         return;
7097         }
7098         else
7099         {
7100                 if (!skinframe->qgeneratemerged)
7101                         return;
7102         }
7103
7104         width = skinframe->qwidth;
7105         height = skinframe->qheight;
7106         skindata = skinframe->qpixels;
7107
7108         if (skinframe->qgeneratenmap)
7109         {
7110                 unsigned char *temp1, *temp2;
7111                 skinframe->qgeneratenmap = false;
7112                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
7113                 temp2 = temp1 + width * height * 4;
7114                 // use either a custom palette or the quake palette
7115                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
7116                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
7117                 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);
7118                 Mem_Free(temp1);
7119         }
7120
7121         if (skinframe->qgenerateglow)
7122         {
7123                 skinframe->qgenerateglow = false;
7124                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
7125         }
7126
7127         if (colormapped)
7128         {
7129                 skinframe->qgeneratebase = false;
7130                 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);
7131                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
7132                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
7133         }
7134         else
7135         {
7136                 skinframe->qgeneratemerged = false;
7137                 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);
7138         }
7139
7140         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
7141         {
7142                 Mem_Free(skinframe->qpixels);
7143                 skinframe->qpixels = NULL;
7144         }
7145 }
7146
7147 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)
7148 {
7149         int i;
7150         skinframe_t *skinframe;
7151
7152         if (cls.state == ca_dedicated)
7153                 return NULL;
7154
7155         // if already loaded just return it, otherwise make a new skinframe
7156         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
7157         if (skinframe && skinframe->base)
7158                 return skinframe;
7159
7160         skinframe->stain = NULL;
7161         skinframe->merged = NULL;
7162         skinframe->base = NULL;
7163         skinframe->pants = NULL;
7164         skinframe->shirt = NULL;
7165         skinframe->nmap = NULL;
7166         skinframe->gloss = NULL;
7167         skinframe->glow = NULL;
7168         skinframe->fog = NULL;
7169         skinframe->reflect = NULL;
7170         skinframe->hasalpha = false;
7171
7172         // if no data was provided, then clearly the caller wanted to get a blank skinframe
7173         if (!skindata)
7174                 return NULL;
7175
7176         if (developer_loading.integer)
7177                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
7178
7179         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
7180         if (textureflags & TEXF_ALPHA)
7181         {
7182                 for (i = 0;i < width * height;i++)
7183                 {
7184                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
7185                         {
7186                                 skinframe->hasalpha = true;
7187                                 break;
7188                         }
7189                 }
7190                 if (r_loadfog && skinframe->hasalpha)
7191                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
7192         }
7193
7194         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
7195         //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]);
7196
7197         return skinframe;
7198 }
7199
7200 skinframe_t *R_SkinFrame_LoadMissing(void)
7201 {
7202         skinframe_t *skinframe;
7203
7204         if (cls.state == ca_dedicated)
7205                 return NULL;
7206
7207         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
7208         skinframe->stain = NULL;
7209         skinframe->merged = NULL;
7210         skinframe->base = NULL;
7211         skinframe->pants = NULL;
7212         skinframe->shirt = NULL;
7213         skinframe->nmap = NULL;
7214         skinframe->gloss = NULL;
7215         skinframe->glow = NULL;
7216         skinframe->fog = NULL;
7217         skinframe->reflect = NULL;
7218         skinframe->hasalpha = false;
7219
7220         skinframe->avgcolor[0] = rand() / RAND_MAX;
7221         skinframe->avgcolor[1] = rand() / RAND_MAX;
7222         skinframe->avgcolor[2] = rand() / RAND_MAX;
7223         skinframe->avgcolor[3] = 1;
7224
7225         return skinframe;
7226 }
7227
7228 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
7229 typedef struct suffixinfo_s
7230 {
7231         const char *suffix;
7232         qboolean flipx, flipy, flipdiagonal;
7233 }
7234 suffixinfo_t;
7235 static suffixinfo_t suffix[3][6] =
7236 {
7237         {
7238                 {"px",   false, false, false},
7239                 {"nx",   false, false, false},
7240                 {"py",   false, false, false},
7241                 {"ny",   false, false, false},
7242                 {"pz",   false, false, false},
7243                 {"nz",   false, false, false}
7244         },
7245         {
7246                 {"posx", false, false, false},
7247                 {"negx", false, false, false},
7248                 {"posy", false, false, false},
7249                 {"negy", false, false, false},
7250                 {"posz", false, false, false},
7251                 {"negz", false, false, false}
7252         },
7253         {
7254                 {"rt",    true, false,  true},
7255                 {"lf",   false,  true,  true},
7256                 {"ft",    true,  true, false},
7257                 {"bk",   false, false, false},
7258                 {"up",    true, false,  true},
7259                 {"dn",    true, false,  true}
7260         }
7261 };
7262
7263 static int componentorder[4] = {0, 1, 2, 3};
7264
7265 rtexture_t *R_LoadCubemap(const char *basename)
7266 {
7267         int i, j, cubemapsize;
7268         unsigned char *cubemappixels, *image_buffer;
7269         rtexture_t *cubemaptexture;
7270         char name[256];
7271         // must start 0 so the first loadimagepixels has no requested width/height
7272         cubemapsize = 0;
7273         cubemappixels = NULL;
7274         cubemaptexture = NULL;
7275         // keep trying different suffix groups (posx, px, rt) until one loads
7276         for (j = 0;j < 3 && !cubemappixels;j++)
7277         {
7278                 // load the 6 images in the suffix group
7279                 for (i = 0;i < 6;i++)
7280                 {
7281                         // generate an image name based on the base and and suffix
7282                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
7283                         // load it
7284                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
7285                         {
7286                                 // an image loaded, make sure width and height are equal
7287                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
7288                                 {
7289                                         // if this is the first image to load successfully, allocate the cubemap memory
7290                                         if (!cubemappixels && image_width >= 1)
7291                                         {
7292                                                 cubemapsize = image_width;
7293                                                 // note this clears to black, so unavailable sides are black
7294                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7295                                         }
7296                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7297                                         if (cubemappixels)
7298                                                 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);
7299                                 }
7300                                 else
7301                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7302                                 // free the image
7303                                 Mem_Free(image_buffer);
7304                         }
7305                 }
7306         }
7307         // if a cubemap loaded, upload it
7308         if (cubemappixels)
7309         {
7310                 if (developer_loading.integer)
7311                         Con_Printf("loading cubemap \"%s\"\n", basename);
7312
7313                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7314                 Mem_Free(cubemappixels);
7315         }
7316         else
7317         {
7318                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7319                 if (developer_loading.integer)
7320                 {
7321                         Con_Printf("(tried tried images ");
7322                         for (j = 0;j < 3;j++)
7323                                 for (i = 0;i < 6;i++)
7324                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7325                         Con_Print(" and was unable to find any of them).\n");
7326                 }
7327         }
7328         return cubemaptexture;
7329 }
7330
7331 rtexture_t *R_GetCubemap(const char *basename)
7332 {
7333         int i;
7334         for (i = 0;i < r_texture_numcubemaps;i++)
7335                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7336                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7337         if (i >= MAX_CUBEMAPS)
7338                 return r_texture_whitecube;
7339         r_texture_numcubemaps++;
7340         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7341         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7342         return r_texture_cubemaps[i].texture;
7343 }
7344
7345 void R_FreeCubemaps(void)
7346 {
7347         int i;
7348         for (i = 0;i < r_texture_numcubemaps;i++)
7349         {
7350                 if (developer_loading.integer)
7351                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7352                 if (r_texture_cubemaps[i].texture)
7353                         R_FreeTexture(r_texture_cubemaps[i].texture);
7354         }
7355         r_texture_numcubemaps = 0;
7356 }
7357
7358 void R_Main_FreeViewCache(void)
7359 {
7360         if (r_refdef.viewcache.entityvisible)
7361                 Mem_Free(r_refdef.viewcache.entityvisible);
7362         if (r_refdef.viewcache.world_pvsbits)
7363                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7364         if (r_refdef.viewcache.world_leafvisible)
7365                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7366         if (r_refdef.viewcache.world_surfacevisible)
7367                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7368         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7369 }
7370
7371 void R_Main_ResizeViewCache(void)
7372 {
7373         int numentities = r_refdef.scene.numentities;
7374         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7375         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7376         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7377         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7378         if (r_refdef.viewcache.maxentities < numentities)
7379         {
7380                 r_refdef.viewcache.maxentities = numentities;
7381                 if (r_refdef.viewcache.entityvisible)
7382                         Mem_Free(r_refdef.viewcache.entityvisible);
7383                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7384         }
7385         if (r_refdef.viewcache.world_numclusters != numclusters)
7386         {
7387                 r_refdef.viewcache.world_numclusters = numclusters;
7388                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7389                 if (r_refdef.viewcache.world_pvsbits)
7390                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7391                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7392         }
7393         if (r_refdef.viewcache.world_numleafs != numleafs)
7394         {
7395                 r_refdef.viewcache.world_numleafs = numleafs;
7396                 if (r_refdef.viewcache.world_leafvisible)
7397                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7398                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7399         }
7400         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7401         {
7402                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7403                 if (r_refdef.viewcache.world_surfacevisible)
7404                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7405                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7406         }
7407 }
7408
7409 extern rtexture_t *loadingscreentexture;
7410 void gl_main_start(void)
7411 {
7412         loadingscreentexture = NULL;
7413         r_texture_blanknormalmap = NULL;
7414         r_texture_white = NULL;
7415         r_texture_grey128 = NULL;
7416         r_texture_black = NULL;
7417         r_texture_whitecube = NULL;
7418         r_texture_normalizationcube = NULL;
7419         r_texture_fogattenuation = NULL;
7420         r_texture_fogheighttexture = NULL;
7421         r_texture_gammaramps = NULL;
7422         r_texture_numcubemaps = 0;
7423
7424         r_loaddds = r_texture_dds_load.integer != 0;
7425         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7426
7427         switch(vid.renderpath)
7428         {
7429         case RENDERPATH_GL20:
7430         case RENDERPATH_CGGL:
7431         case RENDERPATH_D3D9:
7432         case RENDERPATH_D3D10:
7433         case RENDERPATH_D3D11:
7434         case RENDERPATH_SOFT:
7435                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7436                 Cvar_SetValueQuick(&gl_combine, 1);
7437                 Cvar_SetValueQuick(&r_glsl, 1);
7438                 r_loadnormalmap = true;
7439                 r_loadgloss = true;
7440                 r_loadfog = false;
7441                 break;
7442         case RENDERPATH_GL13:
7443                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7444                 Cvar_SetValueQuick(&gl_combine, 1);
7445                 Cvar_SetValueQuick(&r_glsl, 0);
7446                 r_loadnormalmap = false;
7447                 r_loadgloss = false;
7448                 r_loadfog = true;
7449                 break;
7450         case RENDERPATH_GL11:
7451                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7452                 Cvar_SetValueQuick(&gl_combine, 0);
7453                 Cvar_SetValueQuick(&r_glsl, 0);
7454                 r_loadnormalmap = false;
7455                 r_loadgloss = false;
7456                 r_loadfog = true;
7457                 break;
7458         case RENDERPATH_GLES2:
7459                 Cvar_SetValueQuick(&r_textureunits, 1);
7460                 Cvar_SetValueQuick(&gl_combine, 1);
7461                 Cvar_SetValueQuick(&r_glsl, 1);
7462                 r_loadnormalmap = true;
7463                 r_loadgloss = false;
7464                 r_loadfog = false;
7465                 break;
7466         }
7467
7468         R_AnimCache_Free();
7469         R_FrameData_Reset();
7470
7471         r_numqueries = 0;
7472         r_maxqueries = 0;
7473         memset(r_queries, 0, sizeof(r_queries));
7474
7475         r_qwskincache = NULL;
7476         r_qwskincache_size = 0;
7477
7478         // set up r_skinframe loading system for textures
7479         memset(&r_skinframe, 0, sizeof(r_skinframe));
7480         r_skinframe.loadsequence = 1;
7481         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7482
7483         r_main_texturepool = R_AllocTexturePool();
7484         R_BuildBlankTextures();
7485         R_BuildNoTexture();
7486         if (vid.support.arb_texture_cube_map)
7487         {
7488                 R_BuildWhiteCube();
7489                 R_BuildNormalizationCube();
7490         }
7491         r_texture_fogattenuation = NULL;
7492         r_texture_fogheighttexture = NULL;
7493         r_texture_gammaramps = NULL;
7494         //r_texture_fogintensity = NULL;
7495         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7496         memset(&r_waterstate, 0, sizeof(r_waterstate));
7497         r_glsl_permutation = NULL;
7498         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7499         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7500         glslshaderstring = NULL;
7501 #ifdef SUPPORTCG
7502         r_cg_permutation = NULL;
7503         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7504         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7505         cgshaderstring = NULL;
7506 #endif
7507 #ifdef SUPPORTD3D
7508         r_hlsl_permutation = NULL;
7509         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7510         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7511         hlslshaderstring = NULL;
7512 #endif
7513         memset(&r_svbsp, 0, sizeof (r_svbsp));
7514
7515         r_refdef.fogmasktable_density = 0;
7516 }
7517
7518 void gl_main_shutdown(void)
7519 {
7520         R_AnimCache_Free();
7521         R_FrameData_Reset();
7522
7523         R_Main_FreeViewCache();
7524
7525         switch(vid.renderpath)
7526         {
7527         case RENDERPATH_GL11:
7528         case RENDERPATH_GL13:
7529         case RENDERPATH_GL20:
7530         case RENDERPATH_CGGL:
7531                 if (r_maxqueries)
7532                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7533                 break;
7534         case RENDERPATH_D3D9:
7535                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7536                 break;
7537         case RENDERPATH_D3D10:
7538                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7539                 break;
7540         case RENDERPATH_D3D11:
7541                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7542                 break;
7543         case RENDERPATH_SOFT:
7544                 break;
7545         case RENDERPATH_GLES2:
7546                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7547                 break;
7548         }
7549
7550         r_numqueries = 0;
7551         r_maxqueries = 0;
7552         memset(r_queries, 0, sizeof(r_queries));
7553
7554         r_qwskincache = NULL;
7555         r_qwskincache_size = 0;
7556
7557         // clear out the r_skinframe state
7558         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7559         memset(&r_skinframe, 0, sizeof(r_skinframe));
7560
7561         if (r_svbsp.nodes)
7562                 Mem_Free(r_svbsp.nodes);
7563         memset(&r_svbsp, 0, sizeof (r_svbsp));
7564         R_FreeTexturePool(&r_main_texturepool);
7565         loadingscreentexture = NULL;
7566         r_texture_blanknormalmap = NULL;
7567         r_texture_white = NULL;
7568         r_texture_grey128 = NULL;
7569         r_texture_black = NULL;
7570         r_texture_whitecube = NULL;
7571         r_texture_normalizationcube = NULL;
7572         r_texture_fogattenuation = NULL;
7573         r_texture_fogheighttexture = NULL;
7574         r_texture_gammaramps = NULL;
7575         r_texture_numcubemaps = 0;
7576         //r_texture_fogintensity = NULL;
7577         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7578         memset(&r_waterstate, 0, sizeof(r_waterstate));
7579         R_GLSL_Restart_f();
7580
7581         r_glsl_permutation = NULL;
7582         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7583         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
7584         glslshaderstring = NULL;
7585 #ifdef SUPPORTCG
7586         r_cg_permutation = NULL;
7587         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7588         Mem_ExpandableArray_FreeArray(&r_cg_permutationarray);
7589         cgshaderstring = NULL;
7590 #endif
7591 #ifdef SUPPORTD3D
7592         r_hlsl_permutation = NULL;
7593         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7594         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
7595         hlslshaderstring = NULL;
7596 #endif
7597 }
7598
7599 extern void CL_ParseEntityLump(char *entitystring);
7600 void gl_main_newmap(void)
7601 {
7602         // FIXME: move this code to client
7603         char *entities, entname[MAX_QPATH];
7604         if (r_qwskincache)
7605                 Mem_Free(r_qwskincache);
7606         r_qwskincache = NULL;
7607         r_qwskincache_size = 0;
7608         if (cl.worldmodel)
7609         {
7610                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7611                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7612                 {
7613                         CL_ParseEntityLump(entities);
7614                         Mem_Free(entities);
7615                         return;
7616                 }
7617                 if (cl.worldmodel->brush.entities)
7618                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7619         }
7620         R_Main_FreeViewCache();
7621
7622         R_FrameData_Reset();
7623 }
7624
7625 void GL_Main_Init(void)
7626 {
7627         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7628
7629         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7630         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7631         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7632         if (gamemode == GAME_NEHAHRA)
7633         {
7634                 Cvar_RegisterVariable (&gl_fogenable);
7635                 Cvar_RegisterVariable (&gl_fogdensity);
7636                 Cvar_RegisterVariable (&gl_fogred);
7637                 Cvar_RegisterVariable (&gl_foggreen);
7638                 Cvar_RegisterVariable (&gl_fogblue);
7639                 Cvar_RegisterVariable (&gl_fogstart);
7640                 Cvar_RegisterVariable (&gl_fogend);
7641                 Cvar_RegisterVariable (&gl_skyclip);
7642         }
7643         Cvar_RegisterVariable(&r_motionblur);
7644         Cvar_RegisterVariable(&r_motionblur_maxblur);
7645         Cvar_RegisterVariable(&r_motionblur_bmin);
7646         Cvar_RegisterVariable(&r_motionblur_vmin);
7647         Cvar_RegisterVariable(&r_motionblur_vmax);
7648         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7649         Cvar_RegisterVariable(&r_motionblur_randomize);
7650         Cvar_RegisterVariable(&r_damageblur);
7651         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7652         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7653         Cvar_RegisterVariable(&r_equalize_entities_by);
7654         Cvar_RegisterVariable(&r_equalize_entities_to);
7655         Cvar_RegisterVariable(&r_depthfirst);
7656         Cvar_RegisterVariable(&r_useinfinitefarclip);
7657         Cvar_RegisterVariable(&r_farclip_base);
7658         Cvar_RegisterVariable(&r_farclip_world);
7659         Cvar_RegisterVariable(&r_nearclip);
7660         Cvar_RegisterVariable(&r_showbboxes);
7661         Cvar_RegisterVariable(&r_showsurfaces);
7662         Cvar_RegisterVariable(&r_showtris);
7663         Cvar_RegisterVariable(&r_shownormals);
7664         Cvar_RegisterVariable(&r_showlighting);
7665         Cvar_RegisterVariable(&r_showshadowvolumes);
7666         Cvar_RegisterVariable(&r_showcollisionbrushes);
7667         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7668         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7669         Cvar_RegisterVariable(&r_showdisabledepthtest);
7670         Cvar_RegisterVariable(&r_drawportals);
7671         Cvar_RegisterVariable(&r_drawentities);
7672         Cvar_RegisterVariable(&r_draw2d);
7673         Cvar_RegisterVariable(&r_drawworld);
7674         Cvar_RegisterVariable(&r_cullentities_trace);
7675         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7676         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7677         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7678         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7679         Cvar_RegisterVariable(&r_drawviewmodel);
7680         Cvar_RegisterVariable(&r_drawexteriormodel);
7681         Cvar_RegisterVariable(&r_speeds);
7682         Cvar_RegisterVariable(&r_fullbrights);
7683         Cvar_RegisterVariable(&r_wateralpha);
7684         Cvar_RegisterVariable(&r_dynamic);
7685         Cvar_RegisterVariable(&r_fakelight);
7686         Cvar_RegisterVariable(&r_fakelight_intensity);
7687         Cvar_RegisterVariable(&r_fullbright);
7688         Cvar_RegisterVariable(&r_shadows);
7689         Cvar_RegisterVariable(&r_shadows_darken);
7690         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7691         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7692         Cvar_RegisterVariable(&r_shadows_throwdistance);
7693         Cvar_RegisterVariable(&r_shadows_throwdirection);
7694         Cvar_RegisterVariable(&r_shadows_focus);
7695         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7696         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7697         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7698         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7699         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7700         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7701         Cvar_RegisterVariable(&r_fog_exp2);
7702         Cvar_RegisterVariable(&r_drawfog);
7703         Cvar_RegisterVariable(&r_transparentdepthmasking);
7704         Cvar_RegisterVariable(&r_texture_dds_load);
7705         Cvar_RegisterVariable(&r_texture_dds_save);
7706         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7707         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7708         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7709         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7710         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7711         Cvar_RegisterVariable(&r_textureunits);
7712         Cvar_RegisterVariable(&gl_combine);
7713         Cvar_RegisterVariable(&r_glsl);
7714         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7715         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7716         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7717         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7718         Cvar_RegisterVariable(&r_glsl_postprocess);
7719         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7720         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7721         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7722         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7723         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
7724         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
7725         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
7726         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
7727
7728         Cvar_RegisterVariable(&r_water);
7729         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7730         Cvar_RegisterVariable(&r_water_clippingplanebias);
7731         Cvar_RegisterVariable(&r_water_refractdistort);
7732         Cvar_RegisterVariable(&r_water_reflectdistort);
7733         Cvar_RegisterVariable(&r_water_scissormode);
7734         Cvar_RegisterVariable(&r_lerpsprites);
7735         Cvar_RegisterVariable(&r_lerpmodels);
7736         Cvar_RegisterVariable(&r_lerplightstyles);
7737         Cvar_RegisterVariable(&r_waterscroll);
7738         Cvar_RegisterVariable(&r_bloom);
7739         Cvar_RegisterVariable(&r_bloom_colorscale);
7740         Cvar_RegisterVariable(&r_bloom_brighten);
7741         Cvar_RegisterVariable(&r_bloom_blur);
7742         Cvar_RegisterVariable(&r_bloom_resolution);
7743         Cvar_RegisterVariable(&r_bloom_colorexponent);
7744         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7745         Cvar_RegisterVariable(&r_hdr);
7746         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7747         Cvar_RegisterVariable(&r_hdr_glowintensity);
7748         Cvar_RegisterVariable(&r_hdr_range);
7749         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7750         Cvar_RegisterVariable(&developer_texturelogging);
7751         Cvar_RegisterVariable(&gl_lightmaps);
7752         Cvar_RegisterVariable(&r_test);
7753         Cvar_RegisterVariable(&r_glsl_saturation);
7754         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7755         Cvar_RegisterVariable(&r_framedatasize);
7756         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7757                 Cvar_SetValue("r_fullbrights", 0);
7758         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7759
7760         Cvar_RegisterVariable(&r_track_sprites);
7761         Cvar_RegisterVariable(&r_track_sprites_flags);
7762         Cvar_RegisterVariable(&r_track_sprites_scalew);
7763         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7764         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7765         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7766         Cvar_RegisterVariable(&r_overheadsprites_scalex);
7767         Cvar_RegisterVariable(&r_overheadsprites_scaley);
7768 }
7769
7770 extern void R_Textures_Init(void);
7771 extern void GL_Draw_Init(void);
7772 extern void GL_Main_Init(void);
7773 extern void R_Shadow_Init(void);
7774 extern void R_Sky_Init(void);
7775 extern void GL_Surf_Init(void);
7776 extern void R_Particles_Init(void);
7777 extern void R_Explosion_Init(void);
7778 extern void gl_backend_init(void);
7779 extern void Sbar_Init(void);
7780 extern void R_LightningBeams_Init(void);
7781 extern void Mod_RenderInit(void);
7782 extern void Font_Init(void);
7783
7784 void Render_Init(void)
7785 {
7786         gl_backend_init();
7787         R_Textures_Init();
7788         GL_Main_Init();
7789         Font_Init();
7790         GL_Draw_Init();
7791         R_Shadow_Init();
7792         R_Sky_Init();
7793         GL_Surf_Init();
7794         Sbar_Init();
7795         R_Particles_Init();
7796         R_Explosion_Init();
7797         R_LightningBeams_Init();
7798         Mod_RenderInit();
7799 }
7800
7801 /*
7802 ===============
7803 GL_Init
7804 ===============
7805 */
7806 extern char *ENGINE_EXTENSIONS;
7807 void GL_Init (void)
7808 {
7809         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7810         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7811         gl_version = (const char *)qglGetString(GL_VERSION);
7812         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7813
7814         if (!gl_extensions)
7815                 gl_extensions = "";
7816         if (!gl_platformextensions)
7817                 gl_platformextensions = "";
7818
7819         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7820         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7821         Con_Printf("GL_VERSION: %s\n", gl_version);
7822         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7823         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7824
7825         VID_CheckExtensions();
7826
7827         // LordHavoc: report supported extensions
7828         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7829
7830         // clear to black (loading plaque will be seen over this)
7831         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7832 }
7833
7834 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7835 {
7836         int i;
7837         mplane_t *p;
7838         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7839         {
7840                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7841                 if (i == 4)
7842                         continue;
7843                 p = r_refdef.view.frustum + i;
7844                 switch(p->signbits)
7845                 {
7846                 default:
7847                 case 0:
7848                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7849                                 return true;
7850                         break;
7851                 case 1:
7852                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7853                                 return true;
7854                         break;
7855                 case 2:
7856                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7857                                 return true;
7858                         break;
7859                 case 3:
7860                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7861                                 return true;
7862                         break;
7863                 case 4:
7864                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7865                                 return true;
7866                         break;
7867                 case 5:
7868                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7869                                 return true;
7870                         break;
7871                 case 6:
7872                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7873                                 return true;
7874                         break;
7875                 case 7:
7876                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7877                                 return true;
7878                         break;
7879                 }
7880         }
7881         return false;
7882 }
7883
7884 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7885 {
7886         int i;
7887         const mplane_t *p;
7888         for (i = 0;i < numplanes;i++)
7889         {
7890                 p = planes + i;
7891                 switch(p->signbits)
7892                 {
7893                 default:
7894                 case 0:
7895                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7896                                 return true;
7897                         break;
7898                 case 1:
7899                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7900                                 return true;
7901                         break;
7902                 case 2:
7903                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7904                                 return true;
7905                         break;
7906                 case 3:
7907                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7908                                 return true;
7909                         break;
7910                 case 4:
7911                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7912                                 return true;
7913                         break;
7914                 case 5:
7915                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7916                                 return true;
7917                         break;
7918                 case 6:
7919                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7920                                 return true;
7921                         break;
7922                 case 7:
7923                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7924                                 return true;
7925                         break;
7926                 }
7927         }
7928         return false;
7929 }
7930
7931 //==================================================================================
7932
7933 // LordHavoc: this stores temporary data used within the same frame
7934
7935 typedef struct r_framedata_mem_s
7936 {
7937         struct r_framedata_mem_s *purge; // older mem block to free on next frame
7938         size_t size; // how much usable space
7939         size_t current; // how much space in use
7940         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7941         size_t wantedsize; // how much space was allocated
7942         unsigned char *data; // start of real data (16byte aligned)
7943 }
7944 r_framedata_mem_t;
7945
7946 static r_framedata_mem_t *r_framedata_mem;
7947
7948 void R_FrameData_Reset(void)
7949 {
7950         while (r_framedata_mem)
7951         {
7952                 r_framedata_mem_t *next = r_framedata_mem->purge;
7953                 Mem_Free(r_framedata_mem);
7954                 r_framedata_mem = next;
7955         }
7956 }
7957
7958 void R_FrameData_Resize(void)
7959 {
7960         size_t wantedsize;
7961         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7962         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7963         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7964         {
7965                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
7966                 newmem->wantedsize = wantedsize;
7967                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7968                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7969                 newmem->current = 0;
7970                 newmem->mark = 0;
7971                 newmem->purge = r_framedata_mem;
7972                 r_framedata_mem = newmem;
7973         }
7974 }
7975
7976 void R_FrameData_NewFrame(void)
7977 {
7978         R_FrameData_Resize();
7979         if (!r_framedata_mem)
7980                 return;
7981         // if we ran out of space on the last frame, free the old memory now
7982         while (r_framedata_mem->purge)
7983         {
7984                 // repeatedly remove the second item in the list, leaving only head
7985                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7986                 Mem_Free(r_framedata_mem->purge);
7987                 r_framedata_mem->purge = next;
7988         }
7989         // reset the current mem pointer
7990         r_framedata_mem->current = 0;
7991         r_framedata_mem->mark = 0;
7992 }
7993
7994 void *R_FrameData_Alloc(size_t size)
7995 {
7996         void *data;
7997
7998         // align to 16 byte boundary - the data pointer is already aligned, so we
7999         // only need to ensure the size of every allocation is also aligned
8000         size = (size + 15) & ~15;
8001
8002         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
8003         {
8004                 // emergency - we ran out of space, allocate more memory
8005                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
8006                 R_FrameData_Resize();
8007         }
8008
8009         data = r_framedata_mem->data + r_framedata_mem->current;
8010         r_framedata_mem->current += size;
8011
8012         // count the usage for stats
8013         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
8014         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
8015
8016         return (void *)data;
8017 }
8018
8019 void *R_FrameData_Store(size_t size, void *data)
8020 {
8021         void *d = R_FrameData_Alloc(size);
8022         if (d && data)
8023                 memcpy(d, data, size);
8024         return d;
8025 }
8026
8027 void R_FrameData_SetMark(void)
8028 {
8029         if (!r_framedata_mem)
8030                 return;
8031         r_framedata_mem->mark = r_framedata_mem->current;
8032 }
8033
8034 void R_FrameData_ReturnToMark(void)
8035 {
8036         if (!r_framedata_mem)
8037                 return;
8038         r_framedata_mem->current = r_framedata_mem->mark;
8039 }
8040
8041 //==================================================================================
8042
8043 // LordHavoc: animcache originally written by Echon, rewritten since then
8044
8045 /**
8046  * Animation cache prevents re-generating mesh data for an animated model
8047  * multiple times in one frame for lighting, shadowing, reflections, etc.
8048  */
8049
8050 void R_AnimCache_Free(void)
8051 {
8052 }
8053
8054 void R_AnimCache_ClearCache(void)
8055 {
8056         int i;
8057         entity_render_t *ent;
8058
8059         for (i = 0;i < r_refdef.scene.numentities;i++)
8060         {
8061                 ent = r_refdef.scene.entities[i];
8062                 ent->animcache_vertex3f = NULL;
8063                 ent->animcache_normal3f = NULL;
8064                 ent->animcache_svector3f = NULL;
8065                 ent->animcache_tvector3f = NULL;
8066                 ent->animcache_vertexmesh = NULL;
8067                 ent->animcache_vertex3fbuffer = NULL;
8068                 ent->animcache_vertexmeshbuffer = NULL;
8069         }
8070 }
8071
8072 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
8073 {
8074         int i;
8075
8076         // check if we need the meshbuffers
8077         if (!vid.useinterleavedarrays)
8078                 return;
8079
8080         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
8081                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
8082         // TODO: upload vertex3f buffer?
8083         if (ent->animcache_vertexmesh)
8084         {
8085                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
8086                 for (i = 0;i < numvertices;i++)
8087                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
8088                 if (ent->animcache_svector3f)
8089                         for (i = 0;i < numvertices;i++)
8090                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
8091                 if (ent->animcache_tvector3f)
8092                         for (i = 0;i < numvertices;i++)
8093                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
8094                 if (ent->animcache_normal3f)
8095                         for (i = 0;i < numvertices;i++)
8096                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
8097                 // TODO: upload vertexmeshbuffer?
8098         }
8099 }
8100
8101 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
8102 {
8103         dp_model_t *model = ent->model;
8104         int numvertices;
8105         // see if it's already cached this frame
8106         if (ent->animcache_vertex3f)
8107         {
8108                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
8109                 if (wantnormals || wanttangents)
8110                 {
8111                         if (ent->animcache_normal3f)
8112                                 wantnormals = false;
8113                         if (ent->animcache_svector3f)
8114                                 wanttangents = false;
8115                         if (wantnormals || wanttangents)
8116                         {
8117                                 numvertices = model->surfmesh.num_vertices;
8118                                 if (wantnormals)
8119                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
8120                                 if (wanttangents)
8121                                 {
8122                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
8123                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
8124                                 }
8125                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
8126                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
8127                         }
8128                 }
8129         }
8130         else
8131         {
8132                 // see if this ent is worth caching
8133                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
8134                         return false;
8135                 // get some memory for this entity and generate mesh data
8136                 numvertices = model->surfmesh.num_vertices;
8137                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
8138                 if (wantnormals)
8139                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
8140                 if (wanttangents)
8141                 {
8142                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
8143                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
8144                 }
8145                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
8146                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
8147         }
8148         return true;
8149 }
8150
8151 void R_AnimCache_CacheVisibleEntities(void)
8152 {
8153         int i;
8154         qboolean wantnormals = true;
8155         qboolean wanttangents = !r_showsurfaces.integer;
8156
8157         switch(vid.renderpath)
8158         {
8159         case RENDERPATH_GL20:
8160         case RENDERPATH_CGGL:
8161         case RENDERPATH_D3D9:
8162         case RENDERPATH_D3D10:
8163         case RENDERPATH_D3D11:
8164         case RENDERPATH_GLES2:
8165                 break;
8166         case RENDERPATH_GL13:
8167         case RENDERPATH_GL11:
8168                 wanttangents = false;
8169                 break;
8170         case RENDERPATH_SOFT:
8171                 break;
8172         }
8173
8174         if (r_shownormals.integer)
8175                 wanttangents = wantnormals = true;
8176
8177         // TODO: thread this
8178         // NOTE: R_PrepareRTLights() also caches entities
8179
8180         for (i = 0;i < r_refdef.scene.numentities;i++)
8181                 if (r_refdef.viewcache.entityvisible[i])
8182                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
8183 }
8184
8185 //==================================================================================
8186
8187 static void R_View_UpdateEntityLighting (void)
8188 {
8189         int i;
8190         entity_render_t *ent;
8191         vec3_t tempdiffusenormal, avg;
8192         vec_t f, fa, fd, fdd;
8193         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
8194
8195         for (i = 0;i < r_refdef.scene.numentities;i++)
8196         {
8197                 ent = r_refdef.scene.entities[i];
8198
8199                 // skip unseen models
8200                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
8201                         continue;
8202
8203                 // skip bsp models
8204                 if (ent->model && ent->model->brush.num_leafs)
8205                 {
8206                         // TODO: use modellight for r_ambient settings on world?
8207                         VectorSet(ent->modellight_ambient, 0, 0, 0);
8208                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
8209                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
8210                         continue;
8211                 }
8212
8213                 // fetch the lighting from the worldmodel data
8214                 VectorClear(ent->modellight_ambient);
8215                 VectorClear(ent->modellight_diffuse);
8216                 VectorClear(tempdiffusenormal);
8217                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
8218                 {
8219                         vec3_t org;
8220                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8221
8222                         // complete lightning for lit sprites
8223                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
8224                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
8225                         {
8226                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
8227                                         org[2] = org[2] + r_overheadsprites_pushback.value;
8228                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
8229                         }
8230                         else
8231                                 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
8232
8233                         if(ent->flags & RENDER_EQUALIZE)
8234                         {
8235                                 // first fix up ambient lighting...
8236                                 if(r_equalize_entities_minambient.value > 0)
8237                                 {
8238                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
8239                                         if(fd > 0)
8240                                         {
8241                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
8242                                                 if(fa < r_equalize_entities_minambient.value * fd)
8243                                                 {
8244                                                         // solve:
8245                                                         //   fa'/fd' = minambient
8246                                                         //   fa'+0.25*fd' = fa+0.25*fd
8247                                                         //   ...
8248                                                         //   fa' = fd' * minambient
8249                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
8250                                                         //   ...
8251                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
8252                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
8253                                                         //   ...
8254                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
8255                                                         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
8256                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
8257                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
8258                                                 }
8259                                         }
8260                                 }
8261
8262                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
8263                                 {
8264                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
8265                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
8266                                         f = fa + 0.25 * fd;
8267                                         if(f > 0)
8268                                         {
8269                                                 // adjust brightness and saturation to target
8270                                                 avg[0] = avg[1] = avg[2] = fa / f;
8271                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
8272                                                 avg[0] = avg[1] = avg[2] = fd / f;
8273                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
8274                                         }
8275                                 }
8276                         }
8277                 }
8278                 else // highly rare
8279                         VectorSet(ent->modellight_ambient, 1, 1, 1);
8280
8281                 // move the light direction into modelspace coordinates for lighting code
8282                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
8283                 if(VectorLength2(ent->modellight_lightdir) == 0)
8284                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
8285                 VectorNormalize(ent->modellight_lightdir);
8286         }
8287 }
8288
8289 #define MAX_LINEOFSIGHTTRACES 64
8290
8291 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
8292 {
8293         int i;
8294         vec3_t boxmins, boxmaxs;
8295         vec3_t start;
8296         vec3_t end;
8297         dp_model_t *model = r_refdef.scene.worldmodel;
8298
8299         if (!model || !model->brush.TraceLineOfSight)
8300                 return true;
8301
8302         // expand the box a little
8303         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
8304         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
8305         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
8306         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
8307         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
8308         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
8309
8310         // return true if eye is inside enlarged box
8311         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
8312                 return true;
8313
8314         // try center
8315         VectorCopy(eye, start);
8316         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
8317         if (model->brush.TraceLineOfSight(model, start, end))
8318                 return true;
8319
8320         // try various random positions
8321         for (i = 0;i < numsamples;i++)
8322         {
8323                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
8324                 if (model->brush.TraceLineOfSight(model, start, end))
8325                         return true;
8326         }
8327
8328         return false;
8329 }
8330
8331
8332 static void R_View_UpdateEntityVisible (void)
8333 {
8334         int i;
8335         int renderimask;
8336         int samples;
8337         entity_render_t *ent;
8338
8339         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8340                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8341                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
8342                 :                                                          RENDER_EXTERIORMODEL;
8343         if (!r_drawviewmodel.integer)
8344                 renderimask |= RENDER_VIEWMODEL;
8345         if (!r_drawexteriormodel.integer)
8346                 renderimask |= RENDER_EXTERIORMODEL;
8347         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8348         {
8349                 // worldmodel can check visibility
8350                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8351                 for (i = 0;i < r_refdef.scene.numentities;i++)
8352                 {
8353                         ent = r_refdef.scene.entities[i];
8354                         if (!(ent->flags & renderimask))
8355                         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)))
8356                         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))
8357                                 r_refdef.viewcache.entityvisible[i] = true;
8358                 }
8359                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8360                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8361                 {
8362                         for (i = 0;i < r_refdef.scene.numentities;i++)
8363                         {
8364                                 ent = r_refdef.scene.entities[i];
8365                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8366                                 {
8367                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8368                                         if (samples < 0)
8369                                                 continue; // temp entities do pvs only
8370                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8371                                                 ent->last_trace_visibility = realtime;
8372                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8373                                                 r_refdef.viewcache.entityvisible[i] = 0;
8374                                 }
8375                         }
8376                 }
8377         }
8378         else
8379         {
8380                 // no worldmodel or it can't check visibility
8381                 for (i = 0;i < r_refdef.scene.numentities;i++)
8382                 {
8383                         ent = r_refdef.scene.entities[i];
8384                         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));
8385                 }
8386         }
8387 }
8388
8389 /// only used if skyrendermasked, and normally returns false
8390 int R_DrawBrushModelsSky (void)
8391 {
8392         int i, sky;
8393         entity_render_t *ent;
8394
8395         sky = false;
8396         for (i = 0;i < r_refdef.scene.numentities;i++)
8397         {
8398                 if (!r_refdef.viewcache.entityvisible[i])
8399                         continue;
8400                 ent = r_refdef.scene.entities[i];
8401                 if (!ent->model || !ent->model->DrawSky)
8402                         continue;
8403                 ent->model->DrawSky(ent);
8404                 sky = true;
8405         }
8406         return sky;
8407 }
8408
8409 static void R_DrawNoModel(entity_render_t *ent);
8410 static void R_DrawModels(void)
8411 {
8412         int i;
8413         entity_render_t *ent;
8414
8415         for (i = 0;i < r_refdef.scene.numentities;i++)
8416         {
8417                 if (!r_refdef.viewcache.entityvisible[i])
8418                         continue;
8419                 ent = r_refdef.scene.entities[i];
8420                 r_refdef.stats.entities++;
8421                 if (ent->model && ent->model->Draw != NULL)
8422                         ent->model->Draw(ent);
8423                 else
8424                         R_DrawNoModel(ent);
8425         }
8426 }
8427
8428 static void R_DrawModelsDepth(void)
8429 {
8430         int i;
8431         entity_render_t *ent;
8432
8433         for (i = 0;i < r_refdef.scene.numentities;i++)
8434         {
8435                 if (!r_refdef.viewcache.entityvisible[i])
8436                         continue;
8437                 ent = r_refdef.scene.entities[i];
8438                 if (ent->model && ent->model->DrawDepth != NULL)
8439                         ent->model->DrawDepth(ent);
8440         }
8441 }
8442
8443 static void R_DrawModelsDebug(void)
8444 {
8445         int i;
8446         entity_render_t *ent;
8447
8448         for (i = 0;i < r_refdef.scene.numentities;i++)
8449         {
8450                 if (!r_refdef.viewcache.entityvisible[i])
8451                         continue;
8452                 ent = r_refdef.scene.entities[i];
8453                 if (ent->model && ent->model->DrawDebug != NULL)
8454                         ent->model->DrawDebug(ent);
8455         }
8456 }
8457
8458 static void R_DrawModelsAddWaterPlanes(void)
8459 {
8460         int i;
8461         entity_render_t *ent;
8462
8463         for (i = 0;i < r_refdef.scene.numentities;i++)
8464         {
8465                 if (!r_refdef.viewcache.entityvisible[i])
8466                         continue;
8467                 ent = r_refdef.scene.entities[i];
8468                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8469                         ent->model->DrawAddWaterPlanes(ent);
8470         }
8471 }
8472
8473 static void R_View_SetFrustum(const int *scissor)
8474 {
8475         int i;
8476         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8477         vec3_t forward, left, up, origin, v;
8478
8479         if(scissor)
8480         {
8481                 // flipped x coordinates (because x points left here)
8482                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8483                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8484
8485                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8486                 switch(vid.renderpath)
8487                 {
8488                         case RENDERPATH_D3D9:
8489                         case RENDERPATH_D3D10:
8490                         case RENDERPATH_D3D11:
8491                         case RENDERPATH_SOFT:
8492                                 // non-flipped y coordinates
8493                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8494                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8495                                 break;
8496                         case RENDERPATH_GL11:
8497                         case RENDERPATH_GL13:
8498                         case RENDERPATH_GL20:
8499                         case RENDERPATH_CGGL:
8500                         case RENDERPATH_GLES2:
8501                                 // non-flipped y coordinates
8502                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8503                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8504                                 break;
8505                 }
8506         }
8507
8508         // we can't trust r_refdef.view.forward and friends in reflected scenes
8509         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8510
8511 #if 0
8512         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8513         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8514         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8515         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8516         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8517         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8518         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8519         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8520         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8521         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8522         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8523         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8524 #endif
8525
8526 #if 0
8527         zNear = r_refdef.nearclip;
8528         nudge = 1.0 - 1.0 / (1<<23);
8529         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8530         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8531         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8532         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8533         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8534         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8535         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8536         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8537 #endif
8538
8539
8540
8541 #if 0
8542         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8543         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8544         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8545         r_refdef.view.frustum[0].dist = m[15] - m[12];
8546
8547         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8548         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8549         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8550         r_refdef.view.frustum[1].dist = m[15] + m[12];
8551
8552         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8553         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8554         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8555         r_refdef.view.frustum[2].dist = m[15] - m[13];
8556
8557         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8558         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8559         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8560         r_refdef.view.frustum[3].dist = m[15] + m[13];
8561
8562         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8563         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8564         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8565         r_refdef.view.frustum[4].dist = m[15] - m[14];
8566
8567         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8568         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8569         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8570         r_refdef.view.frustum[5].dist = m[15] + m[14];
8571 #endif
8572
8573         if (r_refdef.view.useperspective)
8574         {
8575                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8576                 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]);
8577                 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]);
8578                 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]);
8579                 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]);
8580
8581                 // then the normals from the corners relative to origin
8582                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8583                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8584                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8585                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8586
8587                 // in a NORMAL view, forward cross left == up
8588                 // in a REFLECTED view, forward cross left == down
8589                 // so our cross products above need to be adjusted for a left handed coordinate system
8590                 CrossProduct(forward, left, v);
8591                 if(DotProduct(v, up) < 0)
8592                 {
8593                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8594                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8595                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8596                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8597                 }
8598
8599                 // Leaving those out was a mistake, those were in the old code, and they
8600                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8601                 // I couldn't reproduce it after adding those normalizations. --blub
8602                 VectorNormalize(r_refdef.view.frustum[0].normal);
8603                 VectorNormalize(r_refdef.view.frustum[1].normal);
8604                 VectorNormalize(r_refdef.view.frustum[2].normal);
8605                 VectorNormalize(r_refdef.view.frustum[3].normal);
8606
8607                 // make the corners absolute
8608                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8609                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8610                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8611                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8612
8613                 // one more normal
8614                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8615
8616                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8617                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8618                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8619                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8620                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8621         }
8622         else
8623         {
8624                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8625                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8626                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8627                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8628                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8629                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8630                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8631                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8632                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8633                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8634         }
8635         r_refdef.view.numfrustumplanes = 5;
8636
8637         if (r_refdef.view.useclipplane)
8638         {
8639                 r_refdef.view.numfrustumplanes = 6;
8640                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8641         }
8642
8643         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8644                 PlaneClassify(r_refdef.view.frustum + i);
8645
8646         // LordHavoc: note to all quake engine coders, Quake had a special case
8647         // for 90 degrees which assumed a square view (wrong), so I removed it,
8648         // Quake2 has it disabled as well.
8649
8650         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8651         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8652         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8653         //PlaneClassify(&frustum[0]);
8654
8655         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8656         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8657         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8658         //PlaneClassify(&frustum[1]);
8659
8660         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8661         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8662         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8663         //PlaneClassify(&frustum[2]);
8664
8665         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8666         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8667         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8668         //PlaneClassify(&frustum[3]);
8669
8670         // nearclip plane
8671         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8672         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8673         //PlaneClassify(&frustum[4]);
8674 }
8675
8676 void R_View_UpdateWithScissor(const int *myscissor)
8677 {
8678         R_Main_ResizeViewCache();
8679         R_View_SetFrustum(myscissor);
8680         R_View_WorldVisibility(r_refdef.view.useclipplane);
8681         R_View_UpdateEntityVisible();
8682         R_View_UpdateEntityLighting();
8683 }
8684
8685 void R_View_Update(void)
8686 {
8687         R_Main_ResizeViewCache();
8688         R_View_SetFrustum(NULL);
8689         R_View_WorldVisibility(r_refdef.view.useclipplane);
8690         R_View_UpdateEntityVisible();
8691         R_View_UpdateEntityLighting();
8692 }
8693
8694 void R_SetupView(qboolean allowwaterclippingplane)
8695 {
8696         const float *customclipplane = NULL;
8697         float plane[4];
8698         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8699         {
8700                 // LordHavoc: couldn't figure out how to make this approach the
8701                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8702                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8703                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8704                         dist = r_refdef.view.clipplane.dist;
8705                 plane[0] = r_refdef.view.clipplane.normal[0];
8706                 plane[1] = r_refdef.view.clipplane.normal[1];
8707                 plane[2] = r_refdef.view.clipplane.normal[2];
8708                 plane[3] = dist;
8709                 customclipplane = plane;
8710         }
8711
8712         if (!r_refdef.view.useperspective)
8713                 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);
8714         else if (vid.stencil && r_useinfinitefarclip.integer)
8715                 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);
8716         else
8717                 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);
8718         R_SetViewport(&r_refdef.view.viewport);
8719 }
8720
8721 void R_EntityMatrix(const matrix4x4_t *matrix)
8722 {
8723         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8724         {
8725                 gl_modelmatrixchanged = false;
8726                 gl_modelmatrix = *matrix;
8727                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8728                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8729                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8730                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8731                 CHECKGLERROR
8732                 switch(vid.renderpath)
8733                 {
8734                 case RENDERPATH_D3D9:
8735 #ifdef SUPPORTD3D
8736                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8737                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8738 #endif
8739                         break;
8740                 case RENDERPATH_D3D10:
8741                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8742                         break;
8743                 case RENDERPATH_D3D11:
8744                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8745                         break;
8746                 case RENDERPATH_GL20:
8747                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8748                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8749                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8750                         break;
8751                 case RENDERPATH_CGGL:
8752 #ifdef SUPPORTCG
8753                         CHECKCGERROR
8754                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8755                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8756                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8757 #endif
8758                         break;
8759                 case RENDERPATH_GL13:
8760                 case RENDERPATH_GL11:
8761                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8762                         break;
8763                 case RENDERPATH_SOFT:
8764                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
8765                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
8766                         break;
8767                 case RENDERPATH_GLES2:
8768                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8769                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8770                         break;
8771                 }
8772         }
8773 }
8774
8775 void R_ResetViewRendering2D(void)
8776 {
8777         r_viewport_t viewport;
8778         DrawQ_Finish();
8779
8780         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8781         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);
8782         R_SetViewport(&viewport);
8783         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8784         GL_Color(1, 1, 1, 1);
8785         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8786         GL_BlendFunc(GL_ONE, GL_ZERO);
8787         GL_AlphaTest(false);
8788         GL_ScissorTest(false);
8789         GL_DepthMask(false);
8790         GL_DepthRange(0, 1);
8791         GL_DepthTest(false);
8792         GL_DepthFunc(GL_LEQUAL);
8793         R_EntityMatrix(&identitymatrix);
8794         R_Mesh_ResetTextureState();
8795         GL_PolygonOffset(0, 0);
8796         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8797         switch(vid.renderpath)
8798         {
8799         case RENDERPATH_GL11:
8800         case RENDERPATH_GL13:
8801         case RENDERPATH_GL20:
8802         case RENDERPATH_CGGL:
8803         case RENDERPATH_GLES2:
8804                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8805                 break;
8806         case RENDERPATH_D3D9:
8807         case RENDERPATH_D3D10:
8808         case RENDERPATH_D3D11:
8809         case RENDERPATH_SOFT:
8810                 break;
8811         }
8812         GL_CullFace(GL_NONE);
8813 }
8814
8815 void R_ResetViewRendering3D(void)
8816 {
8817         DrawQ_Finish();
8818
8819         R_SetupView(true);
8820         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8821         GL_Color(1, 1, 1, 1);
8822         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8823         GL_BlendFunc(GL_ONE, GL_ZERO);
8824         GL_AlphaTest(false);
8825         GL_ScissorTest(true);
8826         GL_DepthMask(true);
8827         GL_DepthRange(0, 1);
8828         GL_DepthTest(true);
8829         GL_DepthFunc(GL_LEQUAL);
8830         R_EntityMatrix(&identitymatrix);
8831         R_Mesh_ResetTextureState();
8832         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8833         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8834         switch(vid.renderpath)
8835         {
8836         case RENDERPATH_GL11:
8837         case RENDERPATH_GL13:
8838         case RENDERPATH_GL20:
8839         case RENDERPATH_CGGL:
8840         case RENDERPATH_GLES2:
8841                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8842                 break;
8843         case RENDERPATH_D3D9:
8844         case RENDERPATH_D3D10:
8845         case RENDERPATH_D3D11:
8846         case RENDERPATH_SOFT:
8847                 break;
8848         }
8849         GL_CullFace(r_refdef.view.cullface_back);
8850 }
8851
8852 /*
8853 ================
8854 R_RenderView_UpdateViewVectors
8855 ================
8856 */
8857 static void R_RenderView_UpdateViewVectors(void)
8858 {
8859         // break apart the view matrix into vectors for various purposes
8860         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8861         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8862         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8863         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8864         // make an inverted copy of the view matrix for tracking sprites
8865         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8866 }
8867
8868 void R_RenderScene(void);
8869 void R_RenderWaterPlanes(void);
8870
8871 static void R_Water_StartFrame(void)
8872 {
8873         int i;
8874         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8875         r_waterstate_waterplane_t *p;
8876
8877         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8878                 return;
8879
8880         switch(vid.renderpath)
8881         {
8882         case RENDERPATH_GL20:
8883         case RENDERPATH_CGGL:
8884         case RENDERPATH_D3D9:
8885         case RENDERPATH_D3D10:
8886         case RENDERPATH_D3D11:
8887         case RENDERPATH_SOFT:
8888                 break;
8889         case RENDERPATH_GL13:
8890         case RENDERPATH_GL11:
8891         case RENDERPATH_GLES2:
8892                 return;
8893         }
8894
8895         // set waterwidth and waterheight to the water resolution that will be
8896         // used (often less than the screen resolution for faster rendering)
8897         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8898         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8899
8900         // calculate desired texture sizes
8901         // can't use water if the card does not support the texture size
8902         if (!r_water.integer || r_showsurfaces.integer)
8903                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8904         else if (vid.support.arb_texture_non_power_of_two)
8905         {
8906                 texturewidth = waterwidth;
8907                 textureheight = waterheight;
8908                 camerawidth = waterwidth;
8909                 cameraheight = waterheight;
8910         }
8911         else
8912         {
8913                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8914                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8915                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8916                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8917         }
8918
8919         // allocate textures as needed
8920         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8921         {
8922                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8923                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8924                 {
8925                         if (p->texture_refraction)
8926                                 R_FreeTexture(p->texture_refraction);
8927                         p->texture_refraction = NULL;
8928                         if (p->texture_reflection)
8929                                 R_FreeTexture(p->texture_reflection);
8930                         p->texture_reflection = NULL;
8931                         if (p->texture_camera)
8932                                 R_FreeTexture(p->texture_camera);
8933                         p->texture_camera = NULL;
8934                 }
8935                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8936                 r_waterstate.texturewidth = texturewidth;
8937                 r_waterstate.textureheight = textureheight;
8938                 r_waterstate.camerawidth = camerawidth;
8939                 r_waterstate.cameraheight = cameraheight;
8940         }
8941
8942         if (r_waterstate.texturewidth)
8943         {
8944                 r_waterstate.enabled = true;
8945
8946                 // when doing a reduced render (HDR) we want to use a smaller area
8947                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8948                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8949
8950                 // set up variables that will be used in shader setup
8951                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8952                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8953                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8954                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8955         }
8956
8957         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8958         r_waterstate.numwaterplanes = 0;
8959 }
8960
8961 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8962 {
8963         int triangleindex, planeindex;
8964         const int *e;
8965         vec3_t vert[3];
8966         vec3_t normal;
8967         vec3_t center;
8968         mplane_t plane;
8969         r_waterstate_waterplane_t *p;
8970         texture_t *t = R_GetCurrentTexture(surface->texture);
8971
8972         // just use the first triangle with a valid normal for any decisions
8973         VectorClear(normal);
8974         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8975         {
8976                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8977                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8978                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8979                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8980                 if (VectorLength2(normal) >= 0.001)
8981                         break;
8982         }
8983
8984         VectorCopy(normal, plane.normal);
8985         VectorNormalize(plane.normal);
8986         plane.dist = DotProduct(vert[0], plane.normal);
8987         PlaneClassify(&plane);
8988         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8989         {
8990                 // skip backfaces (except if nocullface is set)
8991                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8992                         return;
8993                 VectorNegate(plane.normal, plane.normal);
8994                 plane.dist *= -1;
8995                 PlaneClassify(&plane);
8996         }
8997
8998
8999         // find a matching plane if there is one
9000         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9001                 if(p->camera_entity == t->camera_entity)
9002                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
9003                                 break;
9004         if (planeindex >= r_waterstate.maxwaterplanes)
9005                 return; // nothing we can do, out of planes
9006
9007         // if this triangle does not fit any known plane rendered this frame, add one
9008         if (planeindex >= r_waterstate.numwaterplanes)
9009         {
9010                 // store the new plane
9011                 r_waterstate.numwaterplanes++;
9012                 p->plane = plane;
9013                 // clear materialflags and pvs
9014                 p->materialflags = 0;
9015                 p->pvsvalid = false;
9016                 p->camera_entity = t->camera_entity;
9017                 VectorCopy(surface->mins, p->mins);
9018                 VectorCopy(surface->maxs, p->maxs);
9019         }
9020         else
9021         {
9022                 // merge mins/maxs
9023                 p->mins[0] = min(p->mins[0], surface->mins[0]);
9024                 p->mins[1] = min(p->mins[1], surface->mins[1]);
9025                 p->mins[2] = min(p->mins[2], surface->mins[2]);
9026                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
9027                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
9028                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
9029         }
9030         // merge this surface's materialflags into the waterplane
9031         p->materialflags |= t->currentmaterialflags;
9032         if(!(p->materialflags & MATERIALFLAG_CAMERA))
9033         {
9034                 // merge this surface's PVS into the waterplane
9035                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
9036                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
9037                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
9038                 {
9039                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
9040                         p->pvsvalid = true;
9041                 }
9042         }
9043 }
9044
9045 static void R_Water_ProcessPlanes(void)
9046 {
9047         int myscissor[4];
9048         r_refdef_view_t originalview;
9049         r_refdef_view_t myview;
9050         int planeindex;
9051         r_waterstate_waterplane_t *p;
9052         vec3_t visorigin;
9053
9054         originalview = r_refdef.view;
9055
9056         // make sure enough textures are allocated
9057         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9058         {
9059                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
9060                 {
9061                         if (!p->texture_refraction)
9062                                 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);
9063                         if (!p->texture_refraction)
9064                                 goto error;
9065                 }
9066                 else if (p->materialflags & MATERIALFLAG_CAMERA)
9067                 {
9068                         if (!p->texture_camera)
9069                                 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);
9070                         if (!p->texture_camera)
9071                                 goto error;
9072                 }
9073
9074                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
9075                 {
9076                         if (!p->texture_reflection)
9077                                 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);
9078                         if (!p->texture_reflection)
9079                                 goto error;
9080                 }
9081         }
9082
9083         // render views
9084         r_refdef.view = originalview;
9085         r_refdef.view.showdebug = false;
9086         r_refdef.view.width = r_waterstate.waterwidth;
9087         r_refdef.view.height = r_waterstate.waterheight;
9088         r_refdef.view.useclipplane = true;
9089         myview = r_refdef.view;
9090         r_waterstate.renderingscene = true;
9091         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9092         {
9093                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
9094                 {
9095                         r_refdef.view = myview;
9096                         if(r_water_scissormode.integer)
9097                         {
9098                                 R_SetupView(true);
9099                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
9100                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
9101                         }
9102
9103                         // render reflected scene and copy into texture
9104                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
9105                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
9106                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
9107                         r_refdef.view.clipplane = p->plane;
9108
9109                         // reverse the cullface settings for this render
9110                         r_refdef.view.cullface_front = GL_FRONT;
9111                         r_refdef.view.cullface_back = GL_BACK;
9112                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
9113                         {
9114                                 r_refdef.view.usecustompvs = true;
9115                                 if (p->pvsvalid)
9116                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
9117                                 else
9118                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
9119                         }
9120
9121                         R_ResetViewRendering3D();
9122                         R_ClearScreen(r_refdef.fogenabled);
9123                         if(r_water_scissormode.integer & 2)
9124                                 R_View_UpdateWithScissor(myscissor);
9125                         else
9126                                 R_View_Update();
9127                         if(r_water_scissormode.integer & 1)
9128                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
9129                         R_RenderScene();
9130
9131                         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);
9132                 }
9133
9134                 // render the normal view scene and copy into texture
9135                 // (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)
9136                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
9137                 {
9138                         r_refdef.view = myview;
9139                         if(r_water_scissormode.integer)
9140                         {
9141                                 R_SetupView(true);
9142                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
9143                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
9144                         }
9145
9146                         r_waterstate.renderingrefraction = true;
9147
9148                         r_refdef.view.clipplane = p->plane;
9149                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
9150                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
9151
9152                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
9153                         {
9154                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
9155                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
9156                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
9157                                 R_RenderView_UpdateViewVectors();
9158                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
9159                                 {
9160                                         r_refdef.view.usecustompvs = true;
9161                                         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);
9162                                 }
9163                         }
9164
9165                         PlaneClassify(&r_refdef.view.clipplane);
9166
9167                         R_ResetViewRendering3D();
9168                         R_ClearScreen(r_refdef.fogenabled);
9169                         if(r_water_scissormode.integer & 2)
9170                                 R_View_UpdateWithScissor(myscissor);
9171                         else
9172                                 R_View_Update();
9173                         if(r_water_scissormode.integer & 1)
9174                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
9175                         R_RenderScene();
9176
9177                         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);
9178                         r_waterstate.renderingrefraction = false;
9179                 }
9180                 else if (p->materialflags & MATERIALFLAG_CAMERA)
9181                 {
9182                         r_refdef.view = myview;
9183
9184                         r_refdef.view.clipplane = p->plane;
9185                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
9186                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
9187
9188                         r_refdef.view.width = r_waterstate.camerawidth;
9189                         r_refdef.view.height = r_waterstate.cameraheight;
9190                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
9191                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
9192
9193                         if(p->camera_entity)
9194                         {
9195                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
9196                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
9197                         }
9198
9199                         // note: all of the view is used for displaying... so
9200                         // there is no use in scissoring
9201
9202                         // reverse the cullface settings for this render
9203                         r_refdef.view.cullface_front = GL_FRONT;
9204                         r_refdef.view.cullface_back = GL_BACK;
9205                         // also reverse the view matrix
9206                         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
9207                         R_RenderView_UpdateViewVectors();
9208                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
9209                         {
9210                                 r_refdef.view.usecustompvs = true;
9211                                 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);
9212                         }
9213                         
9214                         // camera needs no clipplane
9215                         r_refdef.view.useclipplane = false;
9216
9217                         PlaneClassify(&r_refdef.view.clipplane);
9218
9219                         R_ResetViewRendering3D();
9220                         R_ClearScreen(r_refdef.fogenabled);
9221                         R_View_Update();
9222                         R_RenderScene();
9223
9224                         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);
9225                         r_waterstate.renderingrefraction = false;
9226                 }
9227
9228         }
9229         r_waterstate.renderingscene = false;
9230         r_refdef.view = originalview;
9231         R_ResetViewRendering3D();
9232         R_ClearScreen(r_refdef.fogenabled);
9233         R_View_Update();
9234         return;
9235 error:
9236         r_refdef.view = originalview;
9237         r_waterstate.renderingscene = false;
9238         Cvar_SetValueQuick(&r_water, 0);
9239         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
9240         return;
9241 }
9242
9243 void R_Bloom_StartFrame(void)
9244 {
9245         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
9246
9247         switch(vid.renderpath)
9248         {
9249         case RENDERPATH_GL20:
9250         case RENDERPATH_CGGL:
9251         case RENDERPATH_D3D9:
9252         case RENDERPATH_D3D10:
9253         case RENDERPATH_D3D11:
9254         case RENDERPATH_SOFT:
9255                 break;
9256         case RENDERPATH_GL13:
9257         case RENDERPATH_GL11:
9258         case RENDERPATH_GLES2:
9259                 return;
9260         }
9261
9262         // set bloomwidth and bloomheight to the bloom resolution that will be
9263         // used (often less than the screen resolution for faster rendering)
9264         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
9265         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
9266         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
9267         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
9268         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
9269
9270         // calculate desired texture sizes
9271         if (vid.support.arb_texture_non_power_of_two)
9272         {
9273                 screentexturewidth = r_refdef.view.width;
9274                 screentextureheight = r_refdef.view.height;
9275                 bloomtexturewidth = r_bloomstate.bloomwidth;
9276                 bloomtextureheight = r_bloomstate.bloomheight;
9277         }
9278         else
9279         {
9280                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
9281                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
9282                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
9283                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
9284         }
9285
9286         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))
9287         {
9288                 Cvar_SetValueQuick(&r_hdr, 0);
9289                 Cvar_SetValueQuick(&r_bloom, 0);
9290                 Cvar_SetValueQuick(&r_motionblur, 0);
9291                 Cvar_SetValueQuick(&r_damageblur, 0);
9292         }
9293
9294         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)))
9295                 screentexturewidth = screentextureheight = 0;
9296         if (!r_hdr.integer && !r_bloom.integer)
9297                 bloomtexturewidth = bloomtextureheight = 0;
9298
9299         // allocate textures as needed
9300         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
9301         {
9302                 if (r_bloomstate.texture_screen)
9303                         R_FreeTexture(r_bloomstate.texture_screen);
9304                 r_bloomstate.texture_screen = NULL;
9305                 r_bloomstate.screentexturewidth = screentexturewidth;
9306                 r_bloomstate.screentextureheight = screentextureheight;
9307                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
9308                         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);
9309         }
9310         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
9311         {
9312                 if (r_bloomstate.texture_bloom)
9313                         R_FreeTexture(r_bloomstate.texture_bloom);
9314                 r_bloomstate.texture_bloom = NULL;
9315                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
9316                 r_bloomstate.bloomtextureheight = bloomtextureheight;
9317                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
9318                         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);
9319         }
9320
9321         // when doing a reduced render (HDR) we want to use a smaller area
9322         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
9323         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
9324         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
9325         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
9326         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
9327
9328         // set up a texcoord array for the full resolution screen image
9329         // (we have to keep this around to copy back during final render)
9330         r_bloomstate.screentexcoord2f[0] = 0;
9331         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
9332         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
9333         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
9334         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
9335         r_bloomstate.screentexcoord2f[5] = 0;
9336         r_bloomstate.screentexcoord2f[6] = 0;
9337         r_bloomstate.screentexcoord2f[7] = 0;
9338
9339         // set up a texcoord array for the reduced resolution bloom image
9340         // (which will be additive blended over the screen image)
9341         r_bloomstate.bloomtexcoord2f[0] = 0;
9342         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9343         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9344         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9345         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9346         r_bloomstate.bloomtexcoord2f[5] = 0;
9347         r_bloomstate.bloomtexcoord2f[6] = 0;
9348         r_bloomstate.bloomtexcoord2f[7] = 0;
9349
9350         switch(vid.renderpath)
9351         {
9352         case RENDERPATH_GL11:
9353         case RENDERPATH_GL13:
9354         case RENDERPATH_GL20:
9355         case RENDERPATH_CGGL:
9356         case RENDERPATH_SOFT:
9357         case RENDERPATH_GLES2:
9358                 break;
9359         case RENDERPATH_D3D9:
9360         case RENDERPATH_D3D10:
9361         case RENDERPATH_D3D11:
9362                 {
9363                         int i;
9364                         for (i = 0;i < 4;i++)
9365                         {
9366                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
9367                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
9368                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
9369                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
9370                         }
9371                 }
9372                 break;
9373         }
9374
9375         if (r_hdr.integer || r_bloom.integer)
9376         {
9377                 r_bloomstate.enabled = true;
9378                 r_bloomstate.hdr = r_hdr.integer != 0;
9379         }
9380
9381         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);
9382 }
9383
9384 void R_Bloom_CopyBloomTexture(float colorscale)
9385 {
9386         r_refdef.stats.bloom++;
9387
9388         // scale down screen texture to the bloom texture size
9389         CHECKGLERROR
9390         R_SetViewport(&r_bloomstate.viewport);
9391         GL_BlendFunc(GL_ONE, GL_ZERO);
9392         GL_Color(colorscale, colorscale, colorscale, 1);
9393         // 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...
9394         switch(vid.renderpath)
9395         {
9396         case RENDERPATH_GL11:
9397         case RENDERPATH_GL13:
9398         case RENDERPATH_GL20:
9399         case RENDERPATH_CGGL:
9400         case RENDERPATH_SOFT:
9401         case RENDERPATH_GLES2:
9402                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9403                 break;
9404         case RENDERPATH_D3D9:
9405         case RENDERPATH_D3D10:
9406         case RENDERPATH_D3D11:
9407                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9408                 break;
9409         }
9410         // TODO: do boxfilter scale-down in shader?
9411         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9412         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9413         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9414
9415         // we now have a bloom image in the framebuffer
9416         // copy it into the bloom image texture for later processing
9417         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);
9418         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9419 }
9420
9421 void R_Bloom_CopyHDRTexture(void)
9422 {
9423         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);
9424         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9425 }
9426
9427 void R_Bloom_MakeTexture(void)
9428 {
9429         int x, range, dir;
9430         float xoffset, yoffset, r, brighten;
9431
9432         r_refdef.stats.bloom++;
9433
9434         R_ResetViewRendering2D();
9435
9436         // we have a bloom image in the framebuffer
9437         CHECKGLERROR
9438         R_SetViewport(&r_bloomstate.viewport);
9439
9440         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9441         {
9442                 x *= 2;
9443                 r = bound(0, r_bloom_colorexponent.value / x, 1);
9444                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9445                 GL_Color(r,r,r,1);
9446                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9447                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9448                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9449                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9450
9451                 // copy the vertically blurred bloom view to a texture
9452                 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);
9453                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9454         }
9455
9456         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9457         brighten = r_bloom_brighten.value;
9458         if (r_hdr.integer)
9459                 brighten *= r_hdr_range.value;
9460         brighten = sqrt(brighten);
9461         if(range >= 1)
9462                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9463         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9464
9465         for (dir = 0;dir < 2;dir++)
9466         {
9467                 // blend on at multiple vertical offsets to achieve a vertical blur
9468                 // TODO: do offset blends using GLSL
9469                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9470                 GL_BlendFunc(GL_ONE, GL_ZERO);
9471                 for (x = -range;x <= range;x++)
9472                 {
9473                         if (!dir){xoffset = 0;yoffset = x;}
9474                         else {xoffset = x;yoffset = 0;}
9475                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9476                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9477                         // compute a texcoord array with the specified x and y offset
9478                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9479                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9480                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9481                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9482                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9483                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9484                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9485                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9486                         // this r value looks like a 'dot' particle, fading sharply to
9487                         // black at the edges
9488                         // (probably not realistic but looks good enough)
9489                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9490                         //r = brighten/(range*2+1);
9491                         r = brighten / (range * 2 + 1);
9492                         if(range >= 1)
9493                                 r *= (1 - x*x/(float)(range*range));
9494                         GL_Color(r, r, r, 1);
9495                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9496                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9497                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9498                         GL_BlendFunc(GL_ONE, GL_ONE);
9499                 }
9500
9501                 // copy the vertically blurred bloom view to a texture
9502                 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);
9503                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9504         }
9505 }
9506
9507 void R_HDR_RenderBloomTexture(void)
9508 {
9509         int oldwidth, oldheight;
9510         float oldcolorscale;
9511         qboolean oldwaterstate;
9512
9513         oldwaterstate = r_waterstate.enabled;
9514         oldcolorscale = r_refdef.view.colorscale;
9515         oldwidth = r_refdef.view.width;
9516         oldheight = r_refdef.view.height;
9517         r_refdef.view.width = r_bloomstate.bloomwidth;
9518         r_refdef.view.height = r_bloomstate.bloomheight;
9519
9520         if(r_hdr.integer < 2)
9521                 r_waterstate.enabled = false;
9522
9523         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9524         // TODO: add exposure compensation features
9525         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9526
9527         r_refdef.view.showdebug = false;
9528         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9529
9530         R_ResetViewRendering3D();
9531
9532         R_ClearScreen(r_refdef.fogenabled);
9533         if (r_timereport_active)
9534                 R_TimeReport("HDRclear");
9535
9536         R_View_Update();
9537         if (r_timereport_active)
9538                 R_TimeReport("visibility");
9539
9540         // only do secondary renders with HDR if r_hdr is 2 or higher
9541         r_waterstate.numwaterplanes = 0;
9542         if (r_waterstate.enabled)
9543                 R_RenderWaterPlanes();
9544
9545         r_refdef.view.showdebug = true;
9546         R_RenderScene();
9547         r_waterstate.numwaterplanes = 0;
9548
9549         R_ResetViewRendering2D();
9550
9551         R_Bloom_CopyHDRTexture();
9552         R_Bloom_MakeTexture();
9553
9554         // restore the view settings
9555         r_waterstate.enabled = oldwaterstate;
9556         r_refdef.view.width = oldwidth;
9557         r_refdef.view.height = oldheight;
9558         r_refdef.view.colorscale = oldcolorscale;
9559
9560         R_ResetViewRendering3D();
9561
9562         R_ClearScreen(r_refdef.fogenabled);
9563         if (r_timereport_active)
9564                 R_TimeReport("viewclear");
9565 }
9566
9567 static void R_BlendView(void)
9568 {
9569         unsigned int permutation;
9570         float uservecs[4][4];
9571
9572         switch (vid.renderpath)
9573         {
9574         case RENDERPATH_GL20:
9575         case RENDERPATH_CGGL:
9576         case RENDERPATH_D3D9:
9577         case RENDERPATH_D3D10:
9578         case RENDERPATH_D3D11:
9579         case RENDERPATH_SOFT:
9580         case RENDERPATH_GLES2:
9581                 permutation =
9582                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9583                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9584                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9585                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9586                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9587
9588                 if (r_bloomstate.texture_screen)
9589                 {
9590                         // make sure the buffer is available
9591                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9592
9593                         R_ResetViewRendering2D();
9594
9595                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9596                         {
9597                                 // declare variables
9598                                 float speed;
9599                                 static float avgspeed;
9600
9601                                 speed = VectorLength(cl.movement_velocity);
9602
9603                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9604                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9605
9606                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9607                                 speed = bound(0, speed, 1);
9608                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9609
9610                                 // calculate values into a standard alpha
9611                                 cl.motionbluralpha = 1 - exp(-
9612                                                 (
9613                                                  (r_motionblur.value * speed / 80)
9614                                                  +
9615                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9616                                                 )
9617                                                 /
9618                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9619                                            );
9620
9621                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9622                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9623                                 // apply the blur
9624                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9625                                 {
9626                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9627                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9628                                         switch(vid.renderpath)
9629                                         {
9630                                         case RENDERPATH_GL11:
9631                                         case RENDERPATH_GL13:
9632                                         case RENDERPATH_GL20:
9633                                         case RENDERPATH_CGGL:
9634                                         case RENDERPATH_SOFT:
9635                                         case RENDERPATH_GLES2:
9636                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9637                                                 break;
9638                                         case RENDERPATH_D3D9:
9639                                         case RENDERPATH_D3D10:
9640                                         case RENDERPATH_D3D11:
9641                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9642                                                 break;
9643                                         }
9644                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9645                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9646                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9647                                 }
9648                         }
9649
9650                         // copy view into the screen texture
9651                         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);
9652                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9653                 }
9654                 else if (!r_bloomstate.texture_bloom)
9655                 {
9656                         // we may still have to do view tint...
9657                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9658                         {
9659                                 // apply a color tint to the whole view
9660                                 R_ResetViewRendering2D();
9661                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9662                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9663                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9664                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9665                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9666                         }
9667                         break; // no screen processing, no bloom, skip it
9668                 }
9669
9670                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9671                 {
9672                         // render simple bloom effect
9673                         // copy the screen and shrink it and darken it for the bloom process
9674                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9675                         // make the bloom texture
9676                         R_Bloom_MakeTexture();
9677                 }
9678
9679 #if _MSC_VER >= 1400
9680 #define sscanf sscanf_s
9681 #endif
9682                 memset(uservecs, 0, sizeof(uservecs));
9683                 if (r_glsl_postprocess_uservec1_enable.integer)
9684                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9685                 if (r_glsl_postprocess_uservec2_enable.integer)
9686                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9687                 if (r_glsl_postprocess_uservec3_enable.integer)
9688                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9689                 if (r_glsl_postprocess_uservec4_enable.integer)
9690                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9691
9692                 R_ResetViewRendering2D();
9693                 GL_Color(1, 1, 1, 1);
9694                 GL_BlendFunc(GL_ONE, GL_ZERO);
9695
9696                 switch(vid.renderpath)
9697                 {
9698                 case RENDERPATH_GL20:
9699                 case RENDERPATH_GLES2:
9700                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9701                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9702                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
9703                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
9704                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
9705                         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]);
9706                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9707                         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]);
9708                         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]);
9709                         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]);
9710                         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]);
9711                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9712                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9713                         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);
9714                         break;
9715                 case RENDERPATH_CGGL:
9716 #ifdef SUPPORTCG
9717                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9718                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9719                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9720                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9721                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9722                         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
9723                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9724                         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
9725                         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
9726                         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
9727                         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
9728                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9729                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9730                         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);
9731 #endif
9732                         break;
9733                 case RENDERPATH_D3D9:
9734 #ifdef SUPPORTD3D
9735                         // 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...
9736                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9737                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9738                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9739                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9740                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9741                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9742                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9743                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9744                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9745                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9746                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9747                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9748                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9749                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9750 #endif
9751                         break;
9752                 case RENDERPATH_D3D10:
9753                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9754                         break;
9755                 case RENDERPATH_D3D11:
9756                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9757                         break;
9758                 case RENDERPATH_SOFT:
9759                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9760                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
9761                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9762                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9763                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9764                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9765                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9766                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9767                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9768                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9769                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9770                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
9771                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9772                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9773                         break;
9774                 default:
9775                         break;
9776                 }
9777                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9778                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9779                 break;
9780         case RENDERPATH_GL13:
9781         case RENDERPATH_GL11:
9782                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9783                 {
9784                         // apply a color tint to the whole view
9785                         R_ResetViewRendering2D();
9786                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9787                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9788                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9789                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9790                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9791                 }
9792                 break;
9793         }
9794 }
9795
9796 matrix4x4_t r_waterscrollmatrix;
9797
9798 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9799 {
9800         if (r_refdef.fog_density)
9801         {
9802                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9803                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9804                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9805
9806                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9807                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9808                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9809                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9810
9811                 {
9812                         vec3_t fogvec;
9813                         VectorCopy(r_refdef.fogcolor, fogvec);
9814                         //   color.rgb *= ContrastBoost * SceneBrightness;
9815                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9816                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9817                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9818                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9819                 }
9820         }
9821 }
9822
9823 void R_UpdateVariables(void)
9824 {
9825         R_Textures_Frame();
9826
9827         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9828
9829         r_refdef.farclip = r_farclip_base.value;
9830         if (r_refdef.scene.worldmodel)
9831                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9832         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9833
9834         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9835                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9836         r_refdef.polygonfactor = 0;
9837         r_refdef.polygonoffset = 0;
9838         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9839         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9840
9841         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9842         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9843         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
9844         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9845         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9846         if (FAKELIGHT_ENABLED)
9847         {
9848                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9849         }
9850         if (r_showsurfaces.integer)
9851         {
9852                 r_refdef.scene.rtworld = false;
9853                 r_refdef.scene.rtworldshadows = false;
9854                 r_refdef.scene.rtdlight = false;
9855                 r_refdef.scene.rtdlightshadows = false;
9856                 r_refdef.lightmapintensity = 0;
9857         }
9858
9859         if (gamemode == GAME_NEHAHRA)
9860         {
9861                 if (gl_fogenable.integer)
9862                 {
9863                         r_refdef.oldgl_fogenable = true;
9864                         r_refdef.fog_density = gl_fogdensity.value;
9865                         r_refdef.fog_red = gl_fogred.value;
9866                         r_refdef.fog_green = gl_foggreen.value;
9867                         r_refdef.fog_blue = gl_fogblue.value;
9868                         r_refdef.fog_alpha = 1;
9869                         r_refdef.fog_start = 0;
9870                         r_refdef.fog_end = gl_skyclip.value;
9871                         r_refdef.fog_height = 1<<30;
9872                         r_refdef.fog_fadedepth = 128;
9873                 }
9874                 else if (r_refdef.oldgl_fogenable)
9875                 {
9876                         r_refdef.oldgl_fogenable = false;
9877                         r_refdef.fog_density = 0;
9878                         r_refdef.fog_red = 0;
9879                         r_refdef.fog_green = 0;
9880                         r_refdef.fog_blue = 0;
9881                         r_refdef.fog_alpha = 0;
9882                         r_refdef.fog_start = 0;
9883                         r_refdef.fog_end = 0;
9884                         r_refdef.fog_height = 1<<30;
9885                         r_refdef.fog_fadedepth = 128;
9886                 }
9887         }
9888
9889         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9890         r_refdef.fog_start = max(0, r_refdef.fog_start);
9891         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9892
9893         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9894
9895         if (r_refdef.fog_density && r_drawfog.integer)
9896         {
9897                 r_refdef.fogenabled = true;
9898                 // this is the point where the fog reaches 0.9986 alpha, which we
9899                 // consider a good enough cutoff point for the texture
9900                 // (0.9986 * 256 == 255.6)
9901                 if (r_fog_exp2.integer)
9902                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9903                 else
9904                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9905                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9906                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9907                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9908                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9909                         R_BuildFogHeightTexture();
9910                 // fog color was already set
9911                 // update the fog texture
9912                 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)
9913                         R_BuildFogTexture();
9914                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9915                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9916         }
9917         else
9918                 r_refdef.fogenabled = false;
9919
9920         switch(vid.renderpath)
9921         {
9922         case RENDERPATH_GL20:
9923         case RENDERPATH_CGGL:
9924         case RENDERPATH_D3D9:
9925         case RENDERPATH_D3D10:
9926         case RENDERPATH_D3D11:
9927         case RENDERPATH_SOFT:
9928         case RENDERPATH_GLES2:
9929                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9930                 {
9931                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9932                         {
9933                                 // build GLSL gamma texture
9934 #define RAMPWIDTH 256
9935                                 unsigned short ramp[RAMPWIDTH * 3];
9936                                 unsigned char rampbgr[RAMPWIDTH][4];
9937                                 int i;
9938
9939                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9940
9941                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9942                                 for(i = 0; i < RAMPWIDTH; ++i)
9943                                 {
9944                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9945                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9946                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9947                                         rampbgr[i][3] = 0;
9948                                 }
9949                                 if (r_texture_gammaramps)
9950                                 {
9951                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9952                                 }
9953                                 else
9954                                 {
9955                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9956                                 }
9957                         }
9958                 }
9959                 else
9960                 {
9961                         // remove GLSL gamma texture
9962                 }
9963                 break;
9964         case RENDERPATH_GL13:
9965         case RENDERPATH_GL11:
9966                 break;
9967         }
9968 }
9969
9970 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9971 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9972 /*
9973 ================
9974 R_SelectScene
9975 ================
9976 */
9977 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9978         if( scenetype != r_currentscenetype ) {
9979                 // store the old scenetype
9980                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9981                 r_currentscenetype = scenetype;
9982                 // move in the new scene
9983                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9984         }
9985 }
9986
9987 /*
9988 ================
9989 R_GetScenePointer
9990 ================
9991 */
9992 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9993 {
9994         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9995         if( scenetype == r_currentscenetype ) {
9996                 return &r_refdef.scene;
9997         } else {
9998                 return &r_scenes_store[ scenetype ];
9999         }
10000 }
10001
10002 /*
10003 ================
10004 R_RenderView
10005 ================
10006 */
10007 int dpsoftrast_test;
10008 void R_RenderView(void)
10009 {
10010         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
10011
10012         dpsoftrast_test = r_test.integer;
10013
10014         if (r_timereport_active)
10015                 R_TimeReport("start");
10016         r_textureframe++; // used only by R_GetCurrentTexture
10017         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10018
10019         if(R_CompileShader_CheckStaticParms())
10020                 R_GLSL_Restart_f();
10021
10022         if (!r_drawentities.integer)
10023                 r_refdef.scene.numentities = 0;
10024
10025         R_AnimCache_ClearCache();
10026         R_FrameData_NewFrame();
10027
10028         /* adjust for stereo display */
10029         if(R_Stereo_Active())
10030         {
10031                 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);
10032                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
10033         }
10034
10035         if (r_refdef.view.isoverlay)
10036         {
10037                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
10038                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
10039                 R_TimeReport("depthclear");
10040
10041                 r_refdef.view.showdebug = false;
10042
10043                 r_waterstate.enabled = false;
10044                 r_waterstate.numwaterplanes = 0;
10045
10046                 R_RenderScene();
10047
10048                 r_refdef.view.matrix = originalmatrix;
10049
10050                 CHECKGLERROR
10051                 return;
10052         }
10053
10054         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
10055         {
10056                 r_refdef.view.matrix = originalmatrix;
10057                 return; //Host_Error ("R_RenderView: NULL worldmodel");
10058         }
10059
10060         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
10061
10062         R_RenderView_UpdateViewVectors();
10063
10064         R_Shadow_UpdateWorldLightSelection();
10065
10066         R_Bloom_StartFrame();
10067         R_Water_StartFrame();
10068
10069         CHECKGLERROR
10070         if (r_timereport_active)
10071                 R_TimeReport("viewsetup");
10072
10073         R_ResetViewRendering3D();
10074
10075         if (r_refdef.view.clear || r_refdef.fogenabled)
10076         {
10077                 R_ClearScreen(r_refdef.fogenabled);
10078                 if (r_timereport_active)
10079                         R_TimeReport("viewclear");
10080         }
10081         r_refdef.view.clear = true;
10082
10083         // this produces a bloom texture to be used in R_BlendView() later
10084         if (r_hdr.integer && r_bloomstate.bloomwidth)
10085         {
10086                 R_HDR_RenderBloomTexture();
10087                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
10088                 r_textureframe++; // used only by R_GetCurrentTexture
10089         }
10090
10091         r_refdef.view.showdebug = true;
10092
10093         R_View_Update();
10094         if (r_timereport_active)
10095                 R_TimeReport("visibility");
10096
10097         r_waterstate.numwaterplanes = 0;
10098         if (r_waterstate.enabled)
10099                 R_RenderWaterPlanes();
10100
10101         R_RenderScene();
10102         r_waterstate.numwaterplanes = 0;
10103
10104         R_BlendView();
10105         if (r_timereport_active)
10106                 R_TimeReport("blendview");
10107
10108         GL_Scissor(0, 0, vid.width, vid.height);
10109         GL_ScissorTest(false);
10110
10111         r_refdef.view.matrix = originalmatrix;
10112
10113         CHECKGLERROR
10114 }
10115
10116 void R_RenderWaterPlanes(void)
10117 {
10118         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
10119         {
10120                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
10121                 if (r_timereport_active)
10122                         R_TimeReport("waterworld");
10123         }
10124
10125         // don't let sound skip if going slow
10126         if (r_refdef.scene.extraupdate)
10127                 S_ExtraUpdate ();
10128
10129         R_DrawModelsAddWaterPlanes();
10130         if (r_timereport_active)
10131                 R_TimeReport("watermodels");
10132
10133         if (r_waterstate.numwaterplanes)
10134         {
10135                 R_Water_ProcessPlanes();
10136                 if (r_timereport_active)
10137                         R_TimeReport("waterscenes");
10138         }
10139 }
10140
10141 extern void R_DrawLightningBeams (void);
10142 extern void VM_CL_AddPolygonsToMeshQueue (void);
10143 extern void R_DrawPortals (void);
10144 extern cvar_t cl_locs_show;
10145 static void R_DrawLocs(void);
10146 static void R_DrawEntityBBoxes(void);
10147 static void R_DrawModelDecals(void);
10148 extern void R_DrawModelShadows(void);
10149 extern void R_DrawModelShadowMaps(void);
10150 extern cvar_t cl_decals_newsystem;
10151 extern qboolean r_shadow_usingdeferredprepass;
10152 void R_RenderScene(void)
10153 {
10154         qboolean shadowmapping = false;
10155
10156         if (r_timereport_active)
10157                 R_TimeReport("beginscene");
10158
10159         r_refdef.stats.renders++;
10160
10161         R_UpdateFogColor();
10162
10163         // don't let sound skip if going slow
10164         if (r_refdef.scene.extraupdate)
10165                 S_ExtraUpdate ();
10166
10167         R_MeshQueue_BeginScene();
10168
10169         R_SkyStartFrame();
10170
10171         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);
10172
10173         if (r_timereport_active)
10174                 R_TimeReport("skystartframe");
10175
10176         if (cl.csqc_vidvars.drawworld)
10177         {
10178                 // don't let sound skip if going slow
10179                 if (r_refdef.scene.extraupdate)
10180                         S_ExtraUpdate ();
10181
10182                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
10183                 {
10184                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
10185                         if (r_timereport_active)
10186                                 R_TimeReport("worldsky");
10187                 }
10188
10189                 if (R_DrawBrushModelsSky() && r_timereport_active)
10190                         R_TimeReport("bmodelsky");
10191
10192                 if (skyrendermasked && skyrenderlater)
10193                 {
10194                         // we have to force off the water clipping plane while rendering sky
10195                         R_SetupView(false);
10196                         R_Sky();
10197                         R_SetupView(true);
10198                         if (r_timereport_active)
10199                                 R_TimeReport("sky");
10200                 }
10201         }
10202
10203         R_AnimCache_CacheVisibleEntities();
10204         if (r_timereport_active)
10205                 R_TimeReport("animation");
10206
10207         R_Shadow_PrepareLights();
10208         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
10209                 R_Shadow_PrepareModelShadows();
10210         if (r_timereport_active)
10211                 R_TimeReport("preparelights");
10212
10213         if (R_Shadow_ShadowMappingEnabled())
10214                 shadowmapping = true;
10215
10216         if (r_shadow_usingdeferredprepass)
10217                 R_Shadow_DrawPrepass();
10218
10219         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
10220         {
10221                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
10222                 if (r_timereport_active)
10223                         R_TimeReport("worlddepth");
10224         }
10225         if (r_depthfirst.integer >= 2)
10226         {
10227                 R_DrawModelsDepth();
10228                 if (r_timereport_active)
10229                         R_TimeReport("modeldepth");
10230         }
10231
10232         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
10233         {
10234                 R_DrawModelShadowMaps();
10235                 R_ResetViewRendering3D();
10236                 // don't let sound skip if going slow
10237                 if (r_refdef.scene.extraupdate)
10238                         S_ExtraUpdate ();
10239         }
10240
10241         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
10242         {
10243                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
10244                 if (r_timereport_active)
10245                         R_TimeReport("world");
10246         }
10247
10248         // don't let sound skip if going slow
10249         if (r_refdef.scene.extraupdate)
10250                 S_ExtraUpdate ();
10251
10252         R_DrawModels();
10253         if (r_timereport_active)
10254                 R_TimeReport("models");
10255
10256         // don't let sound skip if going slow
10257         if (r_refdef.scene.extraupdate)
10258                 S_ExtraUpdate ();
10259
10260         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
10261         {
10262                 R_DrawModelShadows();
10263                 R_ResetViewRendering3D();
10264                 // don't let sound skip if going slow
10265                 if (r_refdef.scene.extraupdate)
10266                         S_ExtraUpdate ();
10267         }
10268
10269         if (!r_shadow_usingdeferredprepass)
10270         {
10271                 R_Shadow_DrawLights();
10272                 if (r_timereport_active)
10273                         R_TimeReport("rtlights");
10274         }
10275
10276         // don't let sound skip if going slow
10277         if (r_refdef.scene.extraupdate)
10278                 S_ExtraUpdate ();
10279
10280         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
10281         {
10282                 R_DrawModelShadows();
10283                 R_ResetViewRendering3D();
10284                 // don't let sound skip if going slow
10285                 if (r_refdef.scene.extraupdate)
10286                         S_ExtraUpdate ();
10287         }
10288
10289         if (cl.csqc_vidvars.drawworld)
10290         {
10291                 if (cl_decals_newsystem.integer)
10292                 {
10293                         R_DrawModelDecals();
10294                         if (r_timereport_active)
10295                                 R_TimeReport("modeldecals");
10296                 }
10297                 else
10298                 {
10299                         R_DrawDecals();
10300                         if (r_timereport_active)
10301                                 R_TimeReport("decals");
10302                 }
10303
10304                 R_DrawParticles();
10305                 if (r_timereport_active)
10306                         R_TimeReport("particles");
10307
10308                 R_DrawExplosions();
10309                 if (r_timereport_active)
10310                         R_TimeReport("explosions");
10311
10312                 R_DrawLightningBeams();
10313                 if (r_timereport_active)
10314                         R_TimeReport("lightning");
10315         }
10316
10317         VM_CL_AddPolygonsToMeshQueue();
10318
10319         if (r_refdef.view.showdebug)
10320         {
10321                 if (cl_locs_show.integer)
10322                 {
10323                         R_DrawLocs();
10324                         if (r_timereport_active)
10325                                 R_TimeReport("showlocs");
10326                 }
10327
10328                 if (r_drawportals.integer)
10329                 {
10330                         R_DrawPortals();
10331                         if (r_timereport_active)
10332                                 R_TimeReport("portals");
10333                 }
10334
10335                 if (r_showbboxes.value > 0)
10336                 {
10337                         R_DrawEntityBBoxes();
10338                         if (r_timereport_active)
10339                                 R_TimeReport("bboxes");
10340                 }
10341         }
10342
10343         R_MeshQueue_RenderTransparent();
10344         if (r_timereport_active)
10345                 R_TimeReport("drawtrans");
10346
10347         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))
10348         {
10349                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
10350                 if (r_timereport_active)
10351                         R_TimeReport("worlddebug");
10352                 R_DrawModelsDebug();
10353                 if (r_timereport_active)
10354                         R_TimeReport("modeldebug");
10355         }
10356
10357         if (cl.csqc_vidvars.drawworld)
10358         {
10359                 R_Shadow_DrawCoronas();
10360                 if (r_timereport_active)
10361                         R_TimeReport("coronas");
10362         }
10363
10364 #if 0
10365         {
10366                 GL_DepthTest(false);
10367                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10368                 GL_Color(1, 1, 1, 1);
10369                 qglBegin(GL_POLYGON);
10370                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
10371                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
10372                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
10373                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
10374                 qglEnd();
10375                 qglBegin(GL_POLYGON);
10376                 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]);
10377                 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]);
10378                 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]);
10379                 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]);
10380                 qglEnd();
10381                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10382         }
10383 #endif
10384
10385         // don't let sound skip if going slow
10386         if (r_refdef.scene.extraupdate)
10387                 S_ExtraUpdate ();
10388
10389         R_ResetViewRendering2D();
10390 }
10391
10392 static const unsigned short bboxelements[36] =
10393 {
10394         5, 1, 3, 5, 3, 7,
10395         6, 2, 0, 6, 0, 4,
10396         7, 3, 2, 7, 2, 6,
10397         4, 0, 1, 4, 1, 5,
10398         4, 5, 7, 4, 7, 6,
10399         1, 0, 2, 1, 2, 3,
10400 };
10401
10402 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
10403 {
10404         int i;
10405         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
10406
10407         RSurf_ActiveWorldEntity();
10408
10409         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10410         GL_DepthMask(false);
10411         GL_DepthRange(0, 1);
10412         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10413 //      R_Mesh_ResetTextureState();
10414
10415         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
10416         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
10417         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
10418         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
10419         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
10420         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
10421         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
10422         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
10423         R_FillColors(color4f, 8, cr, cg, cb, ca);
10424         if (r_refdef.fogenabled)
10425         {
10426                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
10427                 {
10428                         f1 = RSurf_FogVertex(v);
10429                         f2 = 1 - f1;
10430                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10431                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10432                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10433                 }
10434         }
10435         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10436         R_Mesh_ResetTextureState();
10437         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10438         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10439 }
10440
10441 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10442 {
10443         int i;
10444         float color[4];
10445         prvm_edict_t *edict;
10446         prvm_prog_t *prog_save = prog;
10447
10448         // this function draws bounding boxes of server entities
10449         if (!sv.active)
10450                 return;
10451
10452         GL_CullFace(GL_NONE);
10453         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10454
10455         prog = 0;
10456         SV_VM_Begin();
10457         for (i = 0;i < numsurfaces;i++)
10458         {
10459                 edict = PRVM_EDICT_NUM(surfacelist[i]);
10460                 switch ((int)edict->fields.server->solid)
10461                 {
10462                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
10463                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
10464                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
10465                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10466                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
10467                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
10468                 }
10469                 color[3] *= r_showbboxes.value;
10470                 color[3] = bound(0, color[3], 1);
10471                 GL_DepthTest(!r_showdisabledepthtest.integer);
10472                 GL_CullFace(r_refdef.view.cullface_front);
10473                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10474         }
10475         SV_VM_End();
10476         prog = prog_save;
10477 }
10478
10479 static void R_DrawEntityBBoxes(void)
10480 {
10481         int i;
10482         prvm_edict_t *edict;
10483         vec3_t center;
10484         prvm_prog_t *prog_save = prog;
10485
10486         // this function draws bounding boxes of server entities
10487         if (!sv.active)
10488                 return;
10489
10490         prog = 0;
10491         SV_VM_Begin();
10492         for (i = 0;i < prog->num_edicts;i++)
10493         {
10494                 edict = PRVM_EDICT_NUM(i);
10495                 if (edict->priv.server->free)
10496                         continue;
10497                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10498                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10499                         continue;
10500                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10501                         continue;
10502                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10503                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10504         }
10505         SV_VM_End();
10506         prog = prog_save;
10507 }
10508
10509 static const int nomodelelement3i[24] =
10510 {
10511         5, 2, 0,
10512         5, 1, 2,
10513         5, 0, 3,
10514         5, 3, 1,
10515         0, 2, 4,
10516         2, 1, 4,
10517         3, 0, 4,
10518         1, 3, 4
10519 };
10520
10521 static const unsigned short nomodelelement3s[24] =
10522 {
10523         5, 2, 0,
10524         5, 1, 2,
10525         5, 0, 3,
10526         5, 3, 1,
10527         0, 2, 4,
10528         2, 1, 4,
10529         3, 0, 4,
10530         1, 3, 4
10531 };
10532
10533 static const float nomodelvertex3f[6*3] =
10534 {
10535         -16,   0,   0,
10536          16,   0,   0,
10537           0, -16,   0,
10538           0,  16,   0,
10539           0,   0, -16,
10540           0,   0,  16
10541 };
10542
10543 static const float nomodelcolor4f[6*4] =
10544 {
10545         0.0f, 0.0f, 0.5f, 1.0f,
10546         0.0f, 0.0f, 0.5f, 1.0f,
10547         0.0f, 0.5f, 0.0f, 1.0f,
10548         0.0f, 0.5f, 0.0f, 1.0f,
10549         0.5f, 0.0f, 0.0f, 1.0f,
10550         0.5f, 0.0f, 0.0f, 1.0f
10551 };
10552
10553 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10554 {
10555         int i;
10556         float f1, f2, *c;
10557         float color4f[6*4];
10558
10559         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);
10560
10561         // this is only called once per entity so numsurfaces is always 1, and
10562         // surfacelist is always {0}, so this code does not handle batches
10563
10564         if (rsurface.ent_flags & RENDER_ADDITIVE)
10565         {
10566                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10567                 GL_DepthMask(false);
10568         }
10569         else if (rsurface.colormod[3] < 1)
10570         {
10571                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10572                 GL_DepthMask(false);
10573         }
10574         else
10575         {
10576                 GL_BlendFunc(GL_ONE, GL_ZERO);
10577                 GL_DepthMask(true);
10578         }
10579         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10580         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10581         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10582         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10583         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10584         for (i = 0, c = color4f;i < 6;i++, c += 4)
10585         {
10586                 c[0] *= rsurface.colormod[0];
10587                 c[1] *= rsurface.colormod[1];
10588                 c[2] *= rsurface.colormod[2];
10589                 c[3] *= rsurface.colormod[3];
10590         }
10591         if (r_refdef.fogenabled)
10592         {
10593                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10594                 {
10595                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10596                         f2 = 1 - f1;
10597                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10598                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10599                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10600                 }
10601         }
10602 //      R_Mesh_ResetTextureState();
10603         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10604         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10605         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10606 }
10607
10608 void R_DrawNoModel(entity_render_t *ent)
10609 {
10610         vec3_t org;
10611         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10612         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10613                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10614         else
10615                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10616 }
10617
10618 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10619 {
10620         vec3_t right1, right2, diff, normal;
10621
10622         VectorSubtract (org2, org1, normal);
10623
10624         // calculate 'right' vector for start
10625         VectorSubtract (r_refdef.view.origin, org1, diff);
10626         CrossProduct (normal, diff, right1);
10627         VectorNormalize (right1);
10628
10629         // calculate 'right' vector for end
10630         VectorSubtract (r_refdef.view.origin, org2, diff);
10631         CrossProduct (normal, diff, right2);
10632         VectorNormalize (right2);
10633
10634         vert[ 0] = org1[0] + width * right1[0];
10635         vert[ 1] = org1[1] + width * right1[1];
10636         vert[ 2] = org1[2] + width * right1[2];
10637         vert[ 3] = org1[0] - width * right1[0];
10638         vert[ 4] = org1[1] - width * right1[1];
10639         vert[ 5] = org1[2] - width * right1[2];
10640         vert[ 6] = org2[0] - width * right2[0];
10641         vert[ 7] = org2[1] - width * right2[1];
10642         vert[ 8] = org2[2] - width * right2[2];
10643         vert[ 9] = org2[0] + width * right2[0];
10644         vert[10] = org2[1] + width * right2[1];
10645         vert[11] = org2[2] + width * right2[2];
10646 }
10647
10648 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)
10649 {
10650         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10651         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10652         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10653         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10654         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10655         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10656         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10657         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10658         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10659         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10660         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10661         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10662 }
10663
10664 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10665 {
10666         int i;
10667         float *vertex3f;
10668         float v[3];
10669         VectorSet(v, x, y, z);
10670         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10671                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10672                         break;
10673         if (i == mesh->numvertices)
10674         {
10675                 if (mesh->numvertices < mesh->maxvertices)
10676                 {
10677                         VectorCopy(v, vertex3f);
10678                         mesh->numvertices++;
10679                 }
10680                 return mesh->numvertices;
10681         }
10682         else
10683                 return i;
10684 }
10685
10686 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10687 {
10688         int i;
10689         int *e, element[3];
10690         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10691         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10692         e = mesh->element3i + mesh->numtriangles * 3;
10693         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10694         {
10695                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10696                 if (mesh->numtriangles < mesh->maxtriangles)
10697                 {
10698                         *e++ = element[0];
10699                         *e++ = element[1];
10700                         *e++ = element[2];
10701                         mesh->numtriangles++;
10702                 }
10703                 element[1] = element[2];
10704         }
10705 }
10706
10707 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10708 {
10709         int i;
10710         int *e, element[3];
10711         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10712         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10713         e = mesh->element3i + mesh->numtriangles * 3;
10714         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10715         {
10716                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10717                 if (mesh->numtriangles < mesh->maxtriangles)
10718                 {
10719                         *e++ = element[0];
10720                         *e++ = element[1];
10721                         *e++ = element[2];
10722                         mesh->numtriangles++;
10723                 }
10724                 element[1] = element[2];
10725         }
10726 }
10727
10728 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10729 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10730 {
10731         int planenum, planenum2;
10732         int w;
10733         int tempnumpoints;
10734         mplane_t *plane, *plane2;
10735         double maxdist;
10736         double temppoints[2][256*3];
10737         // figure out how large a bounding box we need to properly compute this brush
10738         maxdist = 0;
10739         for (w = 0;w < numplanes;w++)
10740                 maxdist = max(maxdist, fabs(planes[w].dist));
10741         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10742         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10743         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10744         {
10745                 w = 0;
10746                 tempnumpoints = 4;
10747                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10748                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10749                 {
10750                         if (planenum2 == planenum)
10751                                 continue;
10752                         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);
10753                         w = !w;
10754                 }
10755                 if (tempnumpoints < 3)
10756                         continue;
10757                 // generate elements forming a triangle fan for this polygon
10758                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10759         }
10760 }
10761
10762 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)
10763 {
10764         texturelayer_t *layer;
10765         layer = t->currentlayers + t->currentnumlayers++;
10766         layer->type = type;
10767         layer->depthmask = depthmask;
10768         layer->blendfunc1 = blendfunc1;
10769         layer->blendfunc2 = blendfunc2;
10770         layer->texture = texture;
10771         layer->texmatrix = *matrix;
10772         layer->color[0] = r;
10773         layer->color[1] = g;
10774         layer->color[2] = b;
10775         layer->color[3] = a;
10776 }
10777
10778 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10779 {
10780         if(parms[0] == 0 && parms[1] == 0)
10781                 return false;
10782         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10783                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10784                         return false;
10785         return true;
10786 }
10787
10788 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10789 {
10790         double index, f;
10791         index = parms[2] + r_refdef.scene.time * parms[3];
10792         index -= floor(index);
10793         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10794         {
10795         default:
10796         case Q3WAVEFUNC_NONE:
10797         case Q3WAVEFUNC_NOISE:
10798         case Q3WAVEFUNC_COUNT:
10799                 f = 0;
10800                 break;
10801         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10802         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10803         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10804         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10805         case Q3WAVEFUNC_TRIANGLE:
10806                 index *= 4;
10807                 f = index - floor(index);
10808                 if (index < 1)
10809                         f = f;
10810                 else if (index < 2)
10811                         f = 1 - f;
10812                 else if (index < 3)
10813                         f = -f;
10814                 else
10815                         f = -(1 - f);
10816                 break;
10817         }
10818         f = parms[0] + parms[1] * f;
10819         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10820                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10821         return (float) f;
10822 }
10823
10824 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10825 {
10826         int w, h, idx;
10827         float f;
10828         float tcmat[12];
10829         matrix4x4_t matrix, temp;
10830         switch(tcmod->tcmod)
10831         {
10832                 case Q3TCMOD_COUNT:
10833                 case Q3TCMOD_NONE:
10834                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10835                                 matrix = r_waterscrollmatrix;
10836                         else
10837                                 matrix = identitymatrix;
10838                         break;
10839                 case Q3TCMOD_ENTITYTRANSLATE:
10840                         // this is used in Q3 to allow the gamecode to control texcoord
10841                         // scrolling on the entity, which is not supported in darkplaces yet.
10842                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10843                         break;
10844                 case Q3TCMOD_ROTATE:
10845                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10846                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10847                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10848                         break;
10849                 case Q3TCMOD_SCALE:
10850                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10851                         break;
10852                 case Q3TCMOD_SCROLL:
10853                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10854                         break;
10855                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10856                         w = (int) tcmod->parms[0];
10857                         h = (int) tcmod->parms[1];
10858                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10859                         f = f - floor(f);
10860                         idx = (int) floor(f * w * h);
10861                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10862                         break;
10863                 case Q3TCMOD_STRETCH:
10864                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10865                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10866                         break;
10867                 case Q3TCMOD_TRANSFORM:
10868                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10869                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10870                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10871                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10872                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10873                         break;
10874                 case Q3TCMOD_TURBULENT:
10875                         // this is handled in the RSurf_PrepareVertices function
10876                         matrix = identitymatrix;
10877                         break;
10878         }
10879         temp = *texmatrix;
10880         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10881 }
10882
10883 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10884 {
10885         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10886         char name[MAX_QPATH];
10887         skinframe_t *skinframe;
10888         unsigned char pixels[296*194];
10889         strlcpy(cache->name, skinname, sizeof(cache->name));
10890         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10891         if (developer_loading.integer)
10892                 Con_Printf("loading %s\n", name);
10893         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10894         if (!skinframe || !skinframe->base)
10895         {
10896                 unsigned char *f;
10897                 fs_offset_t filesize;
10898                 skinframe = NULL;
10899                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10900                 if (f)
10901                 {
10902                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10903                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10904                         Mem_Free(f);
10905                 }
10906         }
10907         cache->skinframe = skinframe;
10908 }
10909
10910 texture_t *R_GetCurrentTexture(texture_t *t)
10911 {
10912         int i;
10913         const entity_render_t *ent = rsurface.entity;
10914         dp_model_t *model = ent->model;
10915         q3shaderinfo_layer_tcmod_t *tcmod;
10916
10917         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10918                 return t->currentframe;
10919         t->update_lastrenderframe = r_textureframe;
10920         t->update_lastrenderentity = (void *)ent;
10921
10922         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10923                 t->camera_entity = ent->entitynumber;
10924         else
10925                 t->camera_entity = 0;
10926
10927         // switch to an alternate material if this is a q1bsp animated material
10928         {
10929                 texture_t *texture = t;
10930                 int s = rsurface.ent_skinnum;
10931                 if ((unsigned int)s >= (unsigned int)model->numskins)
10932                         s = 0;
10933                 if (model->skinscenes)
10934                 {
10935                         if (model->skinscenes[s].framecount > 1)
10936                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10937                         else
10938                                 s = model->skinscenes[s].firstframe;
10939                 }
10940                 if (s > 0)
10941                         t = t + s * model->num_surfaces;
10942                 if (t->animated)
10943                 {
10944                         // use an alternate animation if the entity's frame is not 0,
10945                         // and only if the texture has an alternate animation
10946                         if (rsurface.ent_alttextures && t->anim_total[1])
10947                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10948                         else
10949                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10950                 }
10951                 texture->currentframe = t;
10952         }
10953
10954         // update currentskinframe to be a qw skin or animation frame
10955         if (rsurface.ent_qwskin >= 0)
10956         {
10957                 i = rsurface.ent_qwskin;
10958                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10959                 {
10960                         r_qwskincache_size = cl.maxclients;
10961                         if (r_qwskincache)
10962                                 Mem_Free(r_qwskincache);
10963                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10964                 }
10965                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10966                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10967                 t->currentskinframe = r_qwskincache[i].skinframe;
10968                 if (t->currentskinframe == NULL)
10969                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10970         }
10971         else if (t->numskinframes >= 2)
10972                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10973         if (t->backgroundnumskinframes >= 2)
10974                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10975
10976         t->currentmaterialflags = t->basematerialflags;
10977         t->currentalpha = rsurface.colormod[3];
10978         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10979                 t->currentalpha *= r_wateralpha.value;
10980         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10981                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10982         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10983                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10984         if (!(rsurface.ent_flags & RENDER_LIGHT))
10985                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10986         else if (FAKELIGHT_ENABLED)
10987         {
10988                         // no modellight if using fakelight for the map
10989         }
10990         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10991         {
10992                 // pick a model lighting mode
10993                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10994                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10995                 else
10996                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10997         }
10998         if (rsurface.ent_flags & RENDER_ADDITIVE)
10999                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
11000         else if (t->currentalpha < 1)
11001                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
11002         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
11003                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
11004         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
11005                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
11006         if (t->backgroundnumskinframes)
11007                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
11008         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
11009         {
11010                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
11011                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
11012         }
11013         else
11014                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
11015         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
11016                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
11017
11018         // there is no tcmod
11019         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
11020         {
11021                 t->currenttexmatrix = r_waterscrollmatrix;
11022                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
11023         }
11024         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
11025         {
11026                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
11027                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
11028         }
11029
11030         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
11031                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
11032         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
11033                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
11034
11035         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
11036         if (t->currentskinframe->qpixels)
11037                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
11038         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
11039         if (!t->basetexture)
11040                 t->basetexture = r_texture_notexture;
11041         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
11042         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
11043         t->nmaptexture = t->currentskinframe->nmap;
11044         if (!t->nmaptexture)
11045                 t->nmaptexture = r_texture_blanknormalmap;
11046         t->glosstexture = r_texture_black;
11047         t->glowtexture = t->currentskinframe->glow;
11048         t->fogtexture = t->currentskinframe->fog;
11049         t->reflectmasktexture = t->currentskinframe->reflect;
11050         if (t->backgroundnumskinframes)
11051         {
11052                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
11053                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
11054                 t->backgroundglosstexture = r_texture_black;
11055                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
11056                 if (!t->backgroundnmaptexture)
11057                         t->backgroundnmaptexture = r_texture_blanknormalmap;
11058         }
11059         else
11060         {
11061                 t->backgroundbasetexture = r_texture_white;
11062                 t->backgroundnmaptexture = r_texture_blanknormalmap;
11063                 t->backgroundglosstexture = r_texture_black;
11064                 t->backgroundglowtexture = NULL;
11065         }
11066         t->specularpower = r_shadow_glossexponent.value;
11067         // TODO: store reference values for these in the texture?
11068         t->specularscale = 0;
11069         if (r_shadow_gloss.integer > 0)
11070         {
11071                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
11072                 {
11073                         if (r_shadow_glossintensity.value > 0)
11074                         {
11075                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
11076                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
11077                                 t->specularscale = r_shadow_glossintensity.value;
11078                         }
11079                 }
11080                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
11081                 {
11082                         t->glosstexture = r_texture_white;
11083                         t->backgroundglosstexture = r_texture_white;
11084                         t->specularscale = r_shadow_gloss2intensity.value;
11085                         t->specularpower = r_shadow_gloss2exponent.value;
11086                 }
11087         }
11088         t->specularscale *= t->specularscalemod;
11089         t->specularpower *= t->specularpowermod;
11090
11091         // lightmaps mode looks bad with dlights using actual texturing, so turn
11092         // off the colormap and glossmap, but leave the normalmap on as it still
11093         // accurately represents the shading involved
11094         if (gl_lightmaps.integer)
11095         {
11096                 t->basetexture = r_texture_grey128;
11097                 t->pantstexture = r_texture_black;
11098                 t->shirttexture = r_texture_black;
11099                 t->nmaptexture = r_texture_blanknormalmap;
11100                 t->glosstexture = r_texture_black;
11101                 t->glowtexture = NULL;
11102                 t->fogtexture = NULL;
11103                 t->reflectmasktexture = NULL;
11104                 t->backgroundbasetexture = NULL;
11105                 t->backgroundnmaptexture = r_texture_blanknormalmap;
11106                 t->backgroundglosstexture = r_texture_black;
11107                 t->backgroundglowtexture = NULL;
11108                 t->specularscale = 0;
11109                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
11110         }
11111
11112         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
11113         VectorClear(t->dlightcolor);
11114         t->currentnumlayers = 0;
11115         if (t->currentmaterialflags & MATERIALFLAG_WALL)
11116         {
11117                 int blendfunc1, blendfunc2;
11118                 qboolean depthmask;
11119                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
11120                 {
11121                         blendfunc1 = GL_SRC_ALPHA;
11122                         blendfunc2 = GL_ONE;
11123                 }
11124                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
11125                 {
11126                         blendfunc1 = GL_SRC_ALPHA;
11127                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
11128                 }
11129                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11130                 {
11131                         blendfunc1 = t->customblendfunc[0];
11132                         blendfunc2 = t->customblendfunc[1];
11133                 }
11134                 else
11135                 {
11136                         blendfunc1 = GL_ONE;
11137                         blendfunc2 = GL_ZERO;
11138                 }
11139                 // don't colormod evilblend textures
11140                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
11141                         VectorSet(t->lightmapcolor, 1, 1, 1);
11142                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
11143                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11144                 {
11145                         // fullbright is not affected by r_refdef.lightmapintensity
11146                         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]);
11147                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
11148                                 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]);
11149                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
11150                                 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]);
11151                 }
11152                 else
11153                 {
11154                         vec3_t ambientcolor;
11155                         float colorscale;
11156                         // set the color tint used for lights affecting this surface
11157                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
11158                         colorscale = 2;
11159                         // q3bsp has no lightmap updates, so the lightstylevalue that
11160                         // would normally be baked into the lightmap must be
11161                         // applied to the color
11162                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
11163                         if (model->type == mod_brushq3)
11164                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
11165                         colorscale *= r_refdef.lightmapintensity;
11166                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
11167                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
11168                         // basic lit geometry
11169                         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]);
11170                         // add pants/shirt if needed
11171                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
11172                                 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]);
11173                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
11174                                 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]);
11175                         // now add ambient passes if needed
11176                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
11177                         {
11178                                 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]);
11179                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
11180                                         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]);
11181                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
11182                                         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]);
11183                         }
11184                 }
11185                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
11186                         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]);
11187                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
11188                 {
11189                         // if this is opaque use alpha blend which will darken the earlier
11190                         // passes cheaply.
11191                         //
11192                         // if this is an alpha blended material, all the earlier passes
11193                         // were darkened by fog already, so we only need to add the fog
11194                         // color ontop through the fog mask texture
11195                         //
11196                         // if this is an additive blended material, all the earlier passes
11197                         // were darkened by fog already, and we should not add fog color
11198                         // (because the background was not darkened, there is no fog color
11199                         // that was lost behind it).
11200                         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]);
11201                 }
11202         }
11203
11204         return t->currentframe;
11205 }
11206
11207 rsurfacestate_t rsurface;
11208
11209 void RSurf_ActiveWorldEntity(void)
11210 {
11211         dp_model_t *model = r_refdef.scene.worldmodel;
11212         //if (rsurface.entity == r_refdef.scene.worldentity)
11213         //      return;
11214         rsurface.entity = r_refdef.scene.worldentity;
11215         rsurface.skeleton = NULL;
11216         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
11217         rsurface.ent_skinnum = 0;
11218         rsurface.ent_qwskin = -1;
11219         rsurface.ent_shadertime = 0;
11220         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
11221         rsurface.matrix = identitymatrix;
11222         rsurface.inversematrix = identitymatrix;
11223         rsurface.matrixscale = 1;
11224         rsurface.inversematrixscale = 1;
11225         R_EntityMatrix(&identitymatrix);
11226         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
11227         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
11228         rsurface.fograngerecip = r_refdef.fograngerecip;
11229         rsurface.fogheightfade = r_refdef.fogheightfade;
11230         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
11231         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11232         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11233         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11234         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11235         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11236         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11237         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
11238         rsurface.colormod[3] = 1;
11239         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);
11240         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11241         rsurface.frameblend[0].lerp = 1;
11242         rsurface.ent_alttextures = false;
11243         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11244         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11245         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11246         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11247         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11248         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11249         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11250         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11251         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11252         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11253         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11254         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11255         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11256         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11257         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11258         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11259         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11260         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11261         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11262         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11263         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11264         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11265         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11266         rsurface.modelelement3i = model->surfmesh.data_element3i;
11267         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11268         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11269         rsurface.modelelement3s = model->surfmesh.data_element3s;
11270         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11271         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11272         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11273         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11274         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11275         rsurface.modelsurfaces = model->data_surfaces;
11276         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11277         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11278         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
11279         rsurface.modelgeneratedvertex = false;
11280         rsurface.batchgeneratedvertex = false;
11281         rsurface.batchfirstvertex = 0;
11282         rsurface.batchnumvertices = 0;
11283         rsurface.batchfirsttriangle = 0;
11284         rsurface.batchnumtriangles = 0;
11285         rsurface.batchvertex3f  = NULL;
11286         rsurface.batchvertex3f_vertexbuffer = NULL;
11287         rsurface.batchvertex3f_bufferoffset = 0;
11288         rsurface.batchsvector3f = NULL;
11289         rsurface.batchsvector3f_vertexbuffer = NULL;
11290         rsurface.batchsvector3f_bufferoffset = 0;
11291         rsurface.batchtvector3f = NULL;
11292         rsurface.batchtvector3f_vertexbuffer = NULL;
11293         rsurface.batchtvector3f_bufferoffset = 0;
11294         rsurface.batchnormal3f  = NULL;
11295         rsurface.batchnormal3f_vertexbuffer = NULL;
11296         rsurface.batchnormal3f_bufferoffset = 0;
11297         rsurface.batchlightmapcolor4f = NULL;
11298         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11299         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11300         rsurface.batchtexcoordtexture2f = NULL;
11301         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11302         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11303         rsurface.batchtexcoordlightmap2f = NULL;
11304         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11305         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11306         rsurface.batchvertexmesh = NULL;
11307         rsurface.batchvertexmeshbuffer = NULL;
11308         rsurface.batchvertex3fbuffer = NULL;
11309         rsurface.batchelement3i = NULL;
11310         rsurface.batchelement3i_indexbuffer = NULL;
11311         rsurface.batchelement3i_bufferoffset = 0;
11312         rsurface.batchelement3s = NULL;
11313         rsurface.batchelement3s_indexbuffer = NULL;
11314         rsurface.batchelement3s_bufferoffset = 0;
11315         rsurface.passcolor4f = NULL;
11316         rsurface.passcolor4f_vertexbuffer = NULL;
11317         rsurface.passcolor4f_bufferoffset = 0;
11318 }
11319
11320 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
11321 {
11322         dp_model_t *model = ent->model;
11323         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
11324         //      return;
11325         rsurface.entity = (entity_render_t *)ent;
11326         rsurface.skeleton = ent->skeleton;
11327         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
11328         rsurface.ent_skinnum = ent->skinnum;
11329         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;
11330         rsurface.ent_shadertime = ent->shadertime;
11331         rsurface.ent_flags = ent->flags;
11332         rsurface.matrix = ent->matrix;
11333         rsurface.inversematrix = ent->inversematrix;
11334         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11335         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11336         R_EntityMatrix(&rsurface.matrix);
11337         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11338         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11339         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11340         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11341         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11342         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11343         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
11344         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
11345         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
11346         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
11347         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
11348         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
11349         rsurface.colormod[3] = ent->alpha;
11350         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
11351         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
11352         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
11353         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11354         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11355         if (ent->model->brush.submodel && !prepass)
11356         {
11357                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
11358                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
11359         }
11360         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
11361         {
11362                 if (ent->animcache_vertex3f)
11363                 {
11364                         rsurface.modelvertex3f = ent->animcache_vertex3f;
11365                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
11366                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
11367                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
11368                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
11369                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
11370                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
11371                 }
11372                 else if (wanttangents)
11373                 {
11374                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11375                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11376                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11377                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11378                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
11379                         rsurface.modelvertexmesh = NULL;
11380                         rsurface.modelvertexmeshbuffer = NULL;
11381                         rsurface.modelvertex3fbuffer = NULL;
11382                 }
11383                 else if (wantnormals)
11384                 {
11385                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11386                         rsurface.modelsvector3f = NULL;
11387                         rsurface.modeltvector3f = NULL;
11388                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11389                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
11390                         rsurface.modelvertexmesh = NULL;
11391                         rsurface.modelvertexmeshbuffer = NULL;
11392                         rsurface.modelvertex3fbuffer = NULL;
11393                 }
11394                 else
11395                 {
11396                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11397                         rsurface.modelsvector3f = NULL;
11398                         rsurface.modeltvector3f = NULL;
11399                         rsurface.modelnormal3f = NULL;
11400                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
11401                         rsurface.modelvertexmesh = NULL;
11402                         rsurface.modelvertexmeshbuffer = NULL;
11403                         rsurface.modelvertex3fbuffer = NULL;
11404                 }
11405                 rsurface.modelvertex3f_vertexbuffer = 0;
11406                 rsurface.modelvertex3f_bufferoffset = 0;
11407                 rsurface.modelsvector3f_vertexbuffer = 0;
11408                 rsurface.modelsvector3f_bufferoffset = 0;
11409                 rsurface.modeltvector3f_vertexbuffer = 0;
11410                 rsurface.modeltvector3f_bufferoffset = 0;
11411                 rsurface.modelnormal3f_vertexbuffer = 0;
11412                 rsurface.modelnormal3f_bufferoffset = 0;
11413                 rsurface.modelgeneratedvertex = true;
11414         }
11415         else
11416         {
11417                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11418                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11419                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11420                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11421                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11422                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11423                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11424                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11425                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11426                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11427                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11428                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11429                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11430                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11431                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
11432                 rsurface.modelgeneratedvertex = false;
11433         }
11434         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11435         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11436         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11437         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11438         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11439         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11440         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11441         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11442         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11443         rsurface.modelelement3i = model->surfmesh.data_element3i;
11444         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11445         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11446         rsurface.modelelement3s = model->surfmesh.data_element3s;
11447         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11448         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11449         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11450         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11451         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11452         rsurface.modelsurfaces = model->data_surfaces;
11453         rsurface.batchgeneratedvertex = false;
11454         rsurface.batchfirstvertex = 0;
11455         rsurface.batchnumvertices = 0;
11456         rsurface.batchfirsttriangle = 0;
11457         rsurface.batchnumtriangles = 0;
11458         rsurface.batchvertex3f  = NULL;
11459         rsurface.batchvertex3f_vertexbuffer = NULL;
11460         rsurface.batchvertex3f_bufferoffset = 0;
11461         rsurface.batchsvector3f = NULL;
11462         rsurface.batchsvector3f_vertexbuffer = NULL;
11463         rsurface.batchsvector3f_bufferoffset = 0;
11464         rsurface.batchtvector3f = NULL;
11465         rsurface.batchtvector3f_vertexbuffer = NULL;
11466         rsurface.batchtvector3f_bufferoffset = 0;
11467         rsurface.batchnormal3f  = NULL;
11468         rsurface.batchnormal3f_vertexbuffer = NULL;
11469         rsurface.batchnormal3f_bufferoffset = 0;
11470         rsurface.batchlightmapcolor4f = NULL;
11471         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11472         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11473         rsurface.batchtexcoordtexture2f = NULL;
11474         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11475         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11476         rsurface.batchtexcoordlightmap2f = NULL;
11477         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11478         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11479         rsurface.batchvertexmesh = NULL;
11480         rsurface.batchvertexmeshbuffer = NULL;
11481         rsurface.batchvertex3fbuffer = NULL;
11482         rsurface.batchelement3i = NULL;
11483         rsurface.batchelement3i_indexbuffer = NULL;
11484         rsurface.batchelement3i_bufferoffset = 0;
11485         rsurface.batchelement3s = NULL;
11486         rsurface.batchelement3s_indexbuffer = NULL;
11487         rsurface.batchelement3s_bufferoffset = 0;
11488         rsurface.passcolor4f = NULL;
11489         rsurface.passcolor4f_vertexbuffer = NULL;
11490         rsurface.passcolor4f_bufferoffset = 0;
11491 }
11492
11493 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)
11494 {
11495         rsurface.entity = r_refdef.scene.worldentity;
11496         rsurface.skeleton = NULL;
11497         rsurface.ent_skinnum = 0;
11498         rsurface.ent_qwskin = -1;
11499         rsurface.ent_shadertime = shadertime;
11500         rsurface.ent_flags = entflags;
11501         rsurface.modelnumvertices = numvertices;
11502         rsurface.modelnumtriangles = numtriangles;
11503         rsurface.matrix = *matrix;
11504         rsurface.inversematrix = *inversematrix;
11505         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11506         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11507         R_EntityMatrix(&rsurface.matrix);
11508         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11509         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11510         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11511         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11512         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11513         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11514         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11515         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11516         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11517         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11518         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11519         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11520         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);
11521         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11522         rsurface.frameblend[0].lerp = 1;
11523         rsurface.ent_alttextures = false;
11524         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11525         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11526         if (wanttangents)
11527         {
11528                 rsurface.modelvertex3f = (float *)vertex3f;
11529                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11530                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11531                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11532         }
11533         else if (wantnormals)
11534         {
11535                 rsurface.modelvertex3f = (float *)vertex3f;
11536                 rsurface.modelsvector3f = NULL;
11537                 rsurface.modeltvector3f = NULL;
11538                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11539         }
11540         else
11541         {
11542                 rsurface.modelvertex3f = (float *)vertex3f;
11543                 rsurface.modelsvector3f = NULL;
11544                 rsurface.modeltvector3f = NULL;
11545                 rsurface.modelnormal3f = NULL;
11546         }
11547         rsurface.modelvertexmesh = NULL;
11548         rsurface.modelvertexmeshbuffer = NULL;
11549         rsurface.modelvertex3fbuffer = NULL;
11550         rsurface.modelvertex3f_vertexbuffer = 0;
11551         rsurface.modelvertex3f_bufferoffset = 0;
11552         rsurface.modelsvector3f_vertexbuffer = 0;
11553         rsurface.modelsvector3f_bufferoffset = 0;
11554         rsurface.modeltvector3f_vertexbuffer = 0;
11555         rsurface.modeltvector3f_bufferoffset = 0;
11556         rsurface.modelnormal3f_vertexbuffer = 0;
11557         rsurface.modelnormal3f_bufferoffset = 0;
11558         rsurface.modelgeneratedvertex = true;
11559         rsurface.modellightmapcolor4f  = (float *)color4f;
11560         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11561         rsurface.modellightmapcolor4f_bufferoffset = 0;
11562         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
11563         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11564         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11565         rsurface.modeltexcoordlightmap2f  = NULL;
11566         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11567         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11568         rsurface.modelelement3i = (int *)element3i;
11569         rsurface.modelelement3i_indexbuffer = NULL;
11570         rsurface.modelelement3i_bufferoffset = 0;
11571         rsurface.modelelement3s = (unsigned short *)element3s;
11572         rsurface.modelelement3s_indexbuffer = NULL;
11573         rsurface.modelelement3s_bufferoffset = 0;
11574         rsurface.modellightmapoffsets = NULL;
11575         rsurface.modelsurfaces = NULL;
11576         rsurface.batchgeneratedvertex = false;
11577         rsurface.batchfirstvertex = 0;
11578         rsurface.batchnumvertices = 0;
11579         rsurface.batchfirsttriangle = 0;
11580         rsurface.batchnumtriangles = 0;
11581         rsurface.batchvertex3f  = NULL;
11582         rsurface.batchvertex3f_vertexbuffer = NULL;
11583         rsurface.batchvertex3f_bufferoffset = 0;
11584         rsurface.batchsvector3f = NULL;
11585         rsurface.batchsvector3f_vertexbuffer = NULL;
11586         rsurface.batchsvector3f_bufferoffset = 0;
11587         rsurface.batchtvector3f = NULL;
11588         rsurface.batchtvector3f_vertexbuffer = NULL;
11589         rsurface.batchtvector3f_bufferoffset = 0;
11590         rsurface.batchnormal3f  = NULL;
11591         rsurface.batchnormal3f_vertexbuffer = NULL;
11592         rsurface.batchnormal3f_bufferoffset = 0;
11593         rsurface.batchlightmapcolor4f = NULL;
11594         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11595         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11596         rsurface.batchtexcoordtexture2f = NULL;
11597         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11598         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11599         rsurface.batchtexcoordlightmap2f = NULL;
11600         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11601         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11602         rsurface.batchvertexmesh = NULL;
11603         rsurface.batchvertexmeshbuffer = NULL;
11604         rsurface.batchvertex3fbuffer = NULL;
11605         rsurface.batchelement3i = NULL;
11606         rsurface.batchelement3i_indexbuffer = NULL;
11607         rsurface.batchelement3i_bufferoffset = 0;
11608         rsurface.batchelement3s = NULL;
11609         rsurface.batchelement3s_indexbuffer = NULL;
11610         rsurface.batchelement3s_bufferoffset = 0;
11611         rsurface.passcolor4f = NULL;
11612         rsurface.passcolor4f_vertexbuffer = NULL;
11613         rsurface.passcolor4f_bufferoffset = 0;
11614
11615         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11616         {
11617                 if ((wantnormals || wanttangents) && !normal3f)
11618                 {
11619                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11620                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11621                 }
11622                 if (wanttangents && !svector3f)
11623                 {
11624                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11625                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11626                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
11627                 }
11628         }
11629 }
11630
11631 float RSurf_FogPoint(const float *v)
11632 {
11633         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11634         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11635         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11636         float FogHeightFade = r_refdef.fogheightfade;
11637         float fogfrac;
11638         unsigned int fogmasktableindex;
11639         if (r_refdef.fogplaneviewabove)
11640                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11641         else
11642                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11643         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11644         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11645 }
11646
11647 float RSurf_FogVertex(const float *v)
11648 {
11649         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11650         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11651         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11652         float FogHeightFade = rsurface.fogheightfade;
11653         float fogfrac;
11654         unsigned int fogmasktableindex;
11655         if (r_refdef.fogplaneviewabove)
11656                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11657         else
11658                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11659         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11660         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11661 }
11662
11663 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11664 {
11665         int i;
11666         for (i = 0;i < numelements;i++)
11667                 outelement3i[i] = inelement3i[i] + adjust;
11668 }
11669
11670 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11671 extern cvar_t gl_vbo;
11672 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11673 {
11674         int deformindex;
11675         int firsttriangle;
11676         int numtriangles;
11677         int firstvertex;
11678         int endvertex;
11679         int numvertices;
11680         int surfacefirsttriangle;
11681         int surfacenumtriangles;
11682         int surfacefirstvertex;
11683         int surfaceendvertex;
11684         int surfacenumvertices;
11685         int batchnumvertices;
11686         int batchnumtriangles;
11687         int needsupdate;
11688         int i, j;
11689         qboolean gaps;
11690         qboolean dynamicvertex;
11691         float amplitude;
11692         float animpos;
11693         float scale;
11694         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11695         float waveparms[4];
11696         q3shaderinfo_deform_t *deform;
11697         const msurface_t *surface, *firstsurface;
11698         r_vertexmesh_t *vertexmesh;
11699         if (!texturenumsurfaces)
11700                 return;
11701         // find vertex range of this surface batch
11702         gaps = false;
11703         firstsurface = texturesurfacelist[0];
11704         firsttriangle = firstsurface->num_firsttriangle;
11705         batchnumvertices = 0;
11706         batchnumtriangles = 0;
11707         firstvertex = endvertex = firstsurface->num_firstvertex;
11708         for (i = 0;i < texturenumsurfaces;i++)
11709         {
11710                 surface = texturesurfacelist[i];
11711                 if (surface != firstsurface + i)
11712                         gaps = true;
11713                 surfacefirstvertex = surface->num_firstvertex;
11714                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11715                 surfacenumvertices = surface->num_vertices;
11716                 surfacenumtriangles = surface->num_triangles;
11717                 if (firstvertex > surfacefirstvertex)
11718                         firstvertex = surfacefirstvertex;
11719                 if (endvertex < surfaceendvertex)
11720                         endvertex = surfaceendvertex;
11721                 batchnumvertices += surfacenumvertices;
11722                 batchnumtriangles += surfacenumtriangles;
11723         }
11724
11725         // we now know the vertex range used, and if there are any gaps in it
11726         rsurface.batchfirstvertex = firstvertex;
11727         rsurface.batchnumvertices = endvertex - firstvertex;
11728         rsurface.batchfirsttriangle = firsttriangle;
11729         rsurface.batchnumtriangles = batchnumtriangles;
11730
11731         // this variable holds flags for which properties have been updated that
11732         // may require regenerating vertexmesh array...
11733         needsupdate = 0;
11734
11735         // check if any dynamic vertex processing must occur
11736         dynamicvertex = false;
11737
11738         // if there is a chance of animated vertex colors, it's a dynamic batch
11739         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11740         {
11741                 dynamicvertex = true;
11742                 batchneed |= BATCHNEED_NOGAPS;
11743                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
11744         }
11745
11746         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11747         {
11748                 switch (deform->deform)
11749                 {
11750                 default:
11751                 case Q3DEFORM_PROJECTIONSHADOW:
11752                 case Q3DEFORM_TEXT0:
11753                 case Q3DEFORM_TEXT1:
11754                 case Q3DEFORM_TEXT2:
11755                 case Q3DEFORM_TEXT3:
11756                 case Q3DEFORM_TEXT4:
11757                 case Q3DEFORM_TEXT5:
11758                 case Q3DEFORM_TEXT6:
11759                 case Q3DEFORM_TEXT7:
11760                 case Q3DEFORM_NONE:
11761                         break;
11762                 case Q3DEFORM_AUTOSPRITE:
11763                         dynamicvertex = true;
11764                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11765                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11766                         break;
11767                 case Q3DEFORM_AUTOSPRITE2:
11768                         dynamicvertex = true;
11769                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11770                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11771                         break;
11772                 case Q3DEFORM_NORMAL:
11773                         dynamicvertex = true;
11774                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11775                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11776                         break;
11777                 case Q3DEFORM_WAVE:
11778                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11779                                 break; // if wavefunc is a nop, ignore this transform
11780                         dynamicvertex = true;
11781                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11782                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11783                         break;
11784                 case Q3DEFORM_BULGE:
11785                         dynamicvertex = true;
11786                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11787                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11788                         break;
11789                 case Q3DEFORM_MOVE:
11790                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11791                                 break; // if wavefunc is a nop, ignore this transform
11792                         dynamicvertex = true;
11793                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11794                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
11795                         break;
11796                 }
11797         }
11798         switch(rsurface.texture->tcgen.tcgen)
11799         {
11800         default:
11801         case Q3TCGEN_TEXTURE:
11802                 break;
11803         case Q3TCGEN_LIGHTMAP:
11804                 dynamicvertex = true;
11805                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11806                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11807                 break;
11808         case Q3TCGEN_VECTOR:
11809                 dynamicvertex = true;
11810                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11811                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11812                 break;
11813         case Q3TCGEN_ENVIRONMENT:
11814                 dynamicvertex = true;
11815                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11816                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11817                 break;
11818         }
11819         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11820         {
11821                 dynamicvertex = true;
11822                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11823                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11824         }
11825
11826         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11827         {
11828                 dynamicvertex = true;
11829                 batchneed |= BATCHNEED_NOGAPS;
11830                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11831         }
11832
11833         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11834         {
11835                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11836                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11837                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11838                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11839                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11840                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11841                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11842         }
11843
11844         // when the model data has no vertex buffer (dynamic mesh), we need to
11845         // eliminate gaps
11846         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
11847                 batchneed |= BATCHNEED_NOGAPS;
11848
11849         // if needsupdate, we have to do a dynamic vertex batch for sure
11850         if (needsupdate & batchneed)
11851                 dynamicvertex = true;
11852
11853         // see if we need to build vertexmesh from arrays
11854         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11855                 dynamicvertex = true;
11856
11857         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11858         // also some drivers strongly dislike firstvertex
11859         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11860                 dynamicvertex = true;
11861
11862         rsurface.batchvertex3f = rsurface.modelvertex3f;
11863         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11864         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11865         rsurface.batchsvector3f = rsurface.modelsvector3f;
11866         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11867         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11868         rsurface.batchtvector3f = rsurface.modeltvector3f;
11869         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11870         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11871         rsurface.batchnormal3f = rsurface.modelnormal3f;
11872         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11873         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11874         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11875         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11876         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11877         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11878         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11879         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11880         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11881         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11882         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11883         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
11884         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11885         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11886         rsurface.batchelement3i = rsurface.modelelement3i;
11887         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11888         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11889         rsurface.batchelement3s = rsurface.modelelement3s;
11890         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11891         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11892
11893         // if any dynamic vertex processing has to occur in software, we copy the
11894         // entire surface list together before processing to rebase the vertices
11895         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11896         //
11897         // if any gaps exist and we do not have a static vertex buffer, we have to
11898         // copy the surface list together to avoid wasting upload bandwidth on the
11899         // vertices in the gaps.
11900         //
11901         // if gaps exist and we have a static vertex buffer, we still have to
11902         // combine the index buffer ranges into one dynamic index buffer.
11903         //
11904         // in all cases we end up with data that can be drawn in one call.
11905
11906         if (!dynamicvertex)
11907         {
11908                 // static vertex data, just set pointers...
11909                 rsurface.batchgeneratedvertex = false;
11910                 // if there are gaps, we want to build a combined index buffer,
11911                 // otherwise use the original static buffer with an appropriate offset
11912                 if (gaps)
11913                 {
11914                         // build a new triangle elements array for this batch
11915                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11916                         rsurface.batchfirsttriangle = 0;
11917                         numtriangles = 0;
11918                         for (i = 0;i < texturenumsurfaces;i++)
11919                         {
11920                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11921                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11922                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11923                                 numtriangles += surfacenumtriangles;
11924                         }
11925                         rsurface.batchelement3i_indexbuffer = NULL;
11926                         rsurface.batchelement3i_bufferoffset = 0;
11927                         rsurface.batchelement3s = NULL;
11928                         rsurface.batchelement3s_indexbuffer = NULL;
11929                         rsurface.batchelement3s_bufferoffset = 0;
11930                         if (endvertex <= 65536)
11931                         {
11932                                 // make a 16bit (unsigned short) index array if possible
11933                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11934                                 for (i = 0;i < numtriangles*3;i++)
11935                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11936                         }
11937                 }
11938                 return;
11939         }
11940
11941         // something needs software processing, do it for real...
11942         // we only directly handle separate array data in this case and then
11943         // generate interleaved data if needed...
11944         rsurface.batchgeneratedvertex = true;
11945
11946         // now copy the vertex data into a combined array and make an index array
11947         // (this is what Quake3 does all the time)
11948         //if (gaps || rsurface.batchfirstvertex)
11949         {
11950                 rsurface.batchvertex3fbuffer = NULL;
11951                 rsurface.batchvertexmesh = NULL;
11952                 rsurface.batchvertexmeshbuffer = NULL;
11953                 rsurface.batchvertex3f = NULL;
11954                 rsurface.batchvertex3f_vertexbuffer = NULL;
11955                 rsurface.batchvertex3f_bufferoffset = 0;
11956                 rsurface.batchsvector3f = NULL;
11957                 rsurface.batchsvector3f_vertexbuffer = NULL;
11958                 rsurface.batchsvector3f_bufferoffset = 0;
11959                 rsurface.batchtvector3f = NULL;
11960                 rsurface.batchtvector3f_vertexbuffer = NULL;
11961                 rsurface.batchtvector3f_bufferoffset = 0;
11962                 rsurface.batchnormal3f = NULL;
11963                 rsurface.batchnormal3f_vertexbuffer = NULL;
11964                 rsurface.batchnormal3f_bufferoffset = 0;
11965                 rsurface.batchlightmapcolor4f = NULL;
11966                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11967                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11968                 rsurface.batchtexcoordtexture2f = NULL;
11969                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11970                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11971                 rsurface.batchtexcoordlightmap2f = NULL;
11972                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11973                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11974                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11975                 rsurface.batchelement3i_indexbuffer = NULL;
11976                 rsurface.batchelement3i_bufferoffset = 0;
11977                 rsurface.batchelement3s = NULL;
11978                 rsurface.batchelement3s_indexbuffer = NULL;
11979                 rsurface.batchelement3s_bufferoffset = 0;
11980                 // we'll only be setting up certain arrays as needed
11981                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11982                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11983                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11984                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11985                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11986                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11987                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11988                 {
11989                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11990                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11991                 }
11992                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11993                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11994                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11995                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11996                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11997                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11998                 numvertices = 0;
11999                 numtriangles = 0;
12000                 for (i = 0;i < texturenumsurfaces;i++)
12001                 {
12002                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
12003                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
12004                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
12005                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
12006                         // copy only the data requested
12007                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
12008                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
12009                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
12010                         {
12011                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
12012                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
12013                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
12014                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
12015                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
12016                                 {
12017                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
12018                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
12019                                 }
12020                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
12021                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
12022                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
12023                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
12024                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
12025                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
12026                         }
12027                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
12028                         numvertices += surfacenumvertices;
12029                         numtriangles += surfacenumtriangles;
12030                 }
12031
12032                 // generate a 16bit index array as well if possible
12033                 // (in general, dynamic batches fit)
12034                 if (numvertices <= 65536)
12035                 {
12036                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
12037                         for (i = 0;i < numtriangles*3;i++)
12038                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
12039                 }
12040
12041                 // since we've copied everything, the batch now starts at 0
12042                 rsurface.batchfirstvertex = 0;
12043                 rsurface.batchnumvertices = batchnumvertices;
12044                 rsurface.batchfirsttriangle = 0;
12045                 rsurface.batchnumtriangles = batchnumtriangles;
12046         }
12047
12048         // q1bsp surfaces rendered in vertex color mode have to have colors
12049         // calculated based on lightstyles
12050         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
12051         {
12052                 // generate color arrays for the surfaces in this list
12053                 int c[4];
12054                 int scale;
12055                 int size3;
12056                 const int *offsets;
12057                 const unsigned char *lm;
12058                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
12059                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
12060                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
12061                 numvertices = 0;
12062                 for (i = 0;i < texturenumsurfaces;i++)
12063                 {
12064                         surface = texturesurfacelist[i];
12065                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
12066                         surfacenumvertices = surface->num_vertices;
12067                         if (surface->lightmapinfo->samples)
12068                         {
12069                                 for (j = 0;j < surfacenumvertices;j++)
12070                                 {
12071                                         lm = surface->lightmapinfo->samples + offsets[j];
12072                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
12073                                         VectorScale(lm, scale, c);
12074                                         if (surface->lightmapinfo->styles[1] != 255)
12075                                         {
12076                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
12077                                                 lm += size3;
12078                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
12079                                                 VectorMA(c, scale, lm, c);
12080                                                 if (surface->lightmapinfo->styles[2] != 255)
12081                                                 {
12082                                                         lm += size3;
12083                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
12084                                                         VectorMA(c, scale, lm, c);
12085                                                         if (surface->lightmapinfo->styles[3] != 255)
12086                                                         {
12087                                                                 lm += size3;
12088                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
12089                                                                 VectorMA(c, scale, lm, c);
12090                                                         }
12091                                                 }
12092                                         }
12093                                         c[0] >>= 7;
12094                                         c[1] >>= 7;
12095                                         c[2] >>= 7;
12096                                         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);
12097                                         numvertices++;
12098                                 }
12099                         }
12100                         else
12101                         {
12102                                 for (j = 0;j < surfacenumvertices;j++)
12103                                 {
12104                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
12105                                         numvertices++;
12106                                 }
12107                         }
12108                 }
12109         }
12110
12111         // if vertices are deformed (sprite flares and things in maps, possibly
12112         // water waves, bulges and other deformations), modify the copied vertices
12113         // in place
12114         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
12115         {
12116                 switch (deform->deform)
12117                 {
12118                 default:
12119                 case Q3DEFORM_PROJECTIONSHADOW:
12120                 case Q3DEFORM_TEXT0:
12121                 case Q3DEFORM_TEXT1:
12122                 case Q3DEFORM_TEXT2:
12123                 case Q3DEFORM_TEXT3:
12124                 case Q3DEFORM_TEXT4:
12125                 case Q3DEFORM_TEXT5:
12126                 case Q3DEFORM_TEXT6:
12127                 case Q3DEFORM_TEXT7:
12128                 case Q3DEFORM_NONE:
12129                         break;
12130                 case Q3DEFORM_AUTOSPRITE:
12131                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
12132                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
12133                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
12134                         VectorNormalize(newforward);
12135                         VectorNormalize(newright);
12136                         VectorNormalize(newup);
12137 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12138 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12139 //                      rsurface.batchvertex3f_bufferoffset = 0;
12140 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
12141 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
12142 //                      rsurface.batchsvector3f_bufferoffset = 0;
12143 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
12144 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
12145 //                      rsurface.batchtvector3f_bufferoffset = 0;
12146 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12147 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
12148 //                      rsurface.batchnormal3f_bufferoffset = 0;
12149                         // a single autosprite surface can contain multiple sprites...
12150                         for (j = 0;j < batchnumvertices - 3;j += 4)
12151                         {
12152                                 VectorClear(center);
12153                                 for (i = 0;i < 4;i++)
12154                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
12155                                 VectorScale(center, 0.25f, center);
12156                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
12157                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
12158                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
12159                                 for (i = 0;i < 4;i++)
12160                                 {
12161                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
12162                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
12163                                 }
12164                         }
12165                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
12166                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12167                         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);
12168                         break;
12169                 case Q3DEFORM_AUTOSPRITE2:
12170                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
12171                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
12172                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
12173                         VectorNormalize(newforward);
12174                         VectorNormalize(newright);
12175                         VectorNormalize(newup);
12176 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12177 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12178 //                      rsurface.batchvertex3f_bufferoffset = 0;
12179                         {
12180                                 const float *v1, *v2;
12181                                 vec3_t start, end;
12182                                 float f, l;
12183                                 struct
12184                                 {
12185                                         float length2;
12186                                         const float *v1;
12187                                         const float *v2;
12188                                 }
12189                                 shortest[2];
12190                                 memset(shortest, 0, sizeof(shortest));
12191                                 // a single autosprite surface can contain multiple sprites...
12192                                 for (j = 0;j < batchnumvertices - 3;j += 4)
12193                                 {
12194                                         VectorClear(center);
12195                                         for (i = 0;i < 4;i++)
12196                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
12197                                         VectorScale(center, 0.25f, center);
12198                                         // find the two shortest edges, then use them to define the
12199                                         // axis vectors for rotating around the central axis
12200                                         for (i = 0;i < 6;i++)
12201                                         {
12202                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
12203                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
12204                                                 l = VectorDistance2(v1, v2);
12205                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
12206                                                 if (v1[2] != v2[2])
12207                                                         l += (1.0f / 1024.0f);
12208                                                 if (shortest[0].length2 > l || i == 0)
12209                                                 {
12210                                                         shortest[1] = shortest[0];
12211                                                         shortest[0].length2 = l;
12212                                                         shortest[0].v1 = v1;
12213                                                         shortest[0].v2 = v2;
12214                                                 }
12215                                                 else if (shortest[1].length2 > l || i == 1)
12216                                                 {
12217                                                         shortest[1].length2 = l;
12218                                                         shortest[1].v1 = v1;
12219                                                         shortest[1].v2 = v2;
12220                                                 }
12221                                         }
12222                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
12223                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
12224                                         // this calculates the right vector from the shortest edge
12225                                         // and the up vector from the edge midpoints
12226                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
12227                                         VectorNormalize(right);
12228                                         VectorSubtract(end, start, up);
12229                                         VectorNormalize(up);
12230                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
12231                                         VectorSubtract(rsurface.localvieworigin, center, forward);
12232                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
12233                                         VectorNegate(forward, forward);
12234                                         VectorReflect(forward, 0, up, forward);
12235                                         VectorNormalize(forward);
12236                                         CrossProduct(up, forward, newright);
12237                                         VectorNormalize(newright);
12238                                         // rotate the quad around the up axis vector, this is made
12239                                         // especially easy by the fact we know the quad is flat,
12240                                         // so we only have to subtract the center position and
12241                                         // measure distance along the right vector, and then
12242                                         // multiply that by the newright vector and add back the
12243                                         // center position
12244                                         // we also need to subtract the old position to undo the
12245                                         // displacement from the center, which we do with a
12246                                         // DotProduct, the subtraction/addition of center is also
12247                                         // optimized into DotProducts here
12248                                         l = DotProduct(right, center);
12249                                         for (i = 0;i < 4;i++)
12250                                         {
12251                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
12252                                                 f = DotProduct(right, v1) - l;
12253                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
12254                                         }
12255                                 }
12256                         }
12257                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
12258                         {
12259 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12260 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
12261 //                              rsurface.batchnormal3f_bufferoffset = 0;
12262                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12263                         }
12264                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12265                         {
12266 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12267 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12268 //                              rsurface.batchsvector3f_bufferoffset = 0;
12269 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12270 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12271 //                              rsurface.batchtvector3f_bufferoffset = 0;
12272                                 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);
12273                         }
12274                         break;
12275                 case Q3DEFORM_NORMAL:
12276                         // deform the normals to make reflections wavey
12277                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12278                         rsurface.batchnormal3f_vertexbuffer = NULL;
12279                         rsurface.batchnormal3f_bufferoffset = 0;
12280                         for (j = 0;j < batchnumvertices;j++)
12281                         {
12282                                 float vertex[3];
12283                                 float *normal = rsurface.batchnormal3f + 3*j;
12284                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
12285                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
12286                                 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]);
12287                                 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]);
12288                                 VectorNormalize(normal);
12289                         }
12290                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12291                         {
12292 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12293 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12294 //                              rsurface.batchsvector3f_bufferoffset = 0;
12295 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12296 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12297 //                              rsurface.batchtvector3f_bufferoffset = 0;
12298                                 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);
12299                         }
12300                         break;
12301                 case Q3DEFORM_WAVE:
12302                         // deform vertex array to make wavey water and flags and such
12303                         waveparms[0] = deform->waveparms[0];
12304                         waveparms[1] = deform->waveparms[1];
12305                         waveparms[2] = deform->waveparms[2];
12306                         waveparms[3] = deform->waveparms[3];
12307                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
12308                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12309                         // this is how a divisor of vertex influence on deformation
12310                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
12311                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12312 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12313 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12314 //                      rsurface.batchvertex3f_bufferoffset = 0;
12315 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12316 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
12317 //                      rsurface.batchnormal3f_bufferoffset = 0;
12318                         for (j = 0;j < batchnumvertices;j++)
12319                         {
12320                                 // if the wavefunc depends on time, evaluate it per-vertex
12321                                 if (waveparms[3])
12322                                 {
12323                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
12324                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12325                                 }
12326                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
12327                         }
12328                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12329                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12330                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12331                         {
12332 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12333 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12334 //                              rsurface.batchsvector3f_bufferoffset = 0;
12335 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12336 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12337 //                              rsurface.batchtvector3f_bufferoffset = 0;
12338                                 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);
12339                         }
12340                         break;
12341                 case Q3DEFORM_BULGE:
12342                         // deform vertex array to make the surface have moving bulges
12343 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12344 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12345 //                      rsurface.batchvertex3f_bufferoffset = 0;
12346 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12347 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
12348 //                      rsurface.batchnormal3f_bufferoffset = 0;
12349                         for (j = 0;j < batchnumvertices;j++)
12350                         {
12351                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12352                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
12353                         }
12354                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12355                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12356                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12357                         {
12358 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12359 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12360 //                              rsurface.batchsvector3f_bufferoffset = 0;
12361 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12362 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12363 //                              rsurface.batchtvector3f_bufferoffset = 0;
12364                                 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);
12365                         }
12366                         break;
12367                 case Q3DEFORM_MOVE:
12368                         // deform vertex array
12369                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12370                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12371                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12372                         VectorScale(deform->parms, scale, waveparms);
12373 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12374 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12375 //                      rsurface.batchvertex3f_bufferoffset = 0;
12376                         for (j = 0;j < batchnumvertices;j++)
12377                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
12378                         break;
12379                 }
12380         }
12381
12382         // generate texcoords based on the chosen texcoord source
12383         switch(rsurface.texture->tcgen.tcgen)
12384         {
12385         default:
12386         case Q3TCGEN_TEXTURE:
12387                 break;
12388         case Q3TCGEN_LIGHTMAP:
12389 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12390 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12391 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12392                 if (rsurface.batchtexcoordlightmap2f)
12393                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
12394                 break;
12395         case Q3TCGEN_VECTOR:
12396 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12397 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12398 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12399                 for (j = 0;j < batchnumvertices;j++)
12400                 {
12401                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12402                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12403                 }
12404                 break;
12405         case Q3TCGEN_ENVIRONMENT:
12406                 // make environment reflections using a spheremap
12407                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12408                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12409                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12410                 for (j = 0;j < batchnumvertices;j++)
12411                 {
12412                         // identical to Q3A's method, but executed in worldspace so
12413                         // carried models can be shiny too
12414
12415                         float viewer[3], d, reflected[3], worldreflected[3];
12416
12417                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12418                         // VectorNormalize(viewer);
12419
12420                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12421
12422                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12423                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12424                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12425                         // note: this is proportinal to viewer, so we can normalize later
12426
12427                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12428                         VectorNormalize(worldreflected);
12429
12430                         // note: this sphere map only uses world x and z!
12431                         // so positive and negative y will LOOK THE SAME.
12432                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12433                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12434                 }
12435                 break;
12436         }
12437         // the only tcmod that needs software vertex processing is turbulent, so
12438         // check for it here and apply the changes if needed
12439         // and we only support that as the first one
12440         // (handling a mixture of turbulent and other tcmods would be problematic
12441         //  without punting it entirely to a software path)
12442         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12443         {
12444                 amplitude = rsurface.texture->tcmods[0].parms[1];
12445                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12446 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12447 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12448 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12449                 for (j = 0;j < batchnumvertices;j++)
12450                 {
12451                         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);
12452                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12453                 }
12454         }
12455
12456         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12457         {
12458                 // convert the modified arrays to vertex structs
12459 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
12460 //              rsurface.batchvertexmeshbuffer = NULL;
12461                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12462                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12463                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12464                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12465                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12466                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12467                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12468                 {
12469                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12470                         {
12471                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12472                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12473                         }
12474                 }
12475                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12476                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12477                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12478                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12479                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12480                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12481                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12482                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12483                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12484         }
12485 }
12486
12487 void RSurf_DrawBatch(void)
12488 {
12489         // sometimes a zero triangle surface (usually a degenerate patch) makes it
12490         // through the pipeline, killing it earlier in the pipeline would have
12491         // per-surface overhead rather than per-batch overhead, so it's best to
12492         // reject it here, before it hits glDraw.
12493         if (rsurface.batchnumtriangles == 0)
12494                 return;
12495 #if 0
12496         // batch debugging code
12497         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
12498         {
12499                 int i;
12500                 int j;
12501                 int c;
12502                 const int *e;
12503                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
12504                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
12505                 {
12506                         c = e[i];
12507                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
12508                         {
12509                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
12510                                 {
12511                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
12512                                                 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);
12513                                         break;
12514                                 }
12515                         }
12516                 }
12517         }
12518 #endif
12519         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);
12520 }
12521
12522 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12523 {
12524         // pick the closest matching water plane
12525         int planeindex, vertexindex, bestplaneindex = -1;
12526         float d, bestd;
12527         vec3_t vert;
12528         const float *v;
12529         r_waterstate_waterplane_t *p;
12530         qboolean prepared = false;
12531         bestd = 0;
12532         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12533         {
12534                 if(p->camera_entity != rsurface.texture->camera_entity)
12535                         continue;
12536                 d = 0;
12537                 if(!prepared)
12538                 {
12539                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12540                         prepared = true;
12541                         if(rsurface.batchnumvertices == 0)
12542                                 break;
12543                 }
12544                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12545                 {
12546                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12547                         d += fabs(PlaneDiff(vert, &p->plane));
12548                 }
12549                 if (bestd > d || bestplaneindex < 0)
12550                 {
12551                         bestd = d;
12552                         bestplaneindex = planeindex;
12553                 }
12554         }
12555         return bestplaneindex;
12556         // NOTE: this MAY return a totally unrelated water plane; we can ignore
12557         // this situation though, as it might be better to render single larger
12558         // batches with useless stuff (backface culled for example) than to
12559         // render multiple smaller batches
12560 }
12561
12562 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12563 {
12564         int i;
12565         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12566         rsurface.passcolor4f_vertexbuffer = 0;
12567         rsurface.passcolor4f_bufferoffset = 0;
12568         for (i = 0;i < rsurface.batchnumvertices;i++)
12569                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12570 }
12571
12572 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12573 {
12574         int i;
12575         float f;
12576         const float *v;
12577         const float *c;
12578         float *c2;
12579         if (rsurface.passcolor4f)
12580         {
12581                 // generate color arrays
12582                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
12583                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12584                 rsurface.passcolor4f_vertexbuffer = 0;
12585                 rsurface.passcolor4f_bufferoffset = 0;
12586                 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)
12587                 {
12588                         f = RSurf_FogVertex(v);
12589                         c2[0] = c[0] * f;
12590                         c2[1] = c[1] * f;
12591                         c2[2] = c[2] * f;
12592                         c2[3] = c[3];
12593                 }
12594         }
12595         else
12596         {
12597                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12598                 rsurface.passcolor4f_vertexbuffer = 0;
12599                 rsurface.passcolor4f_bufferoffset = 0;
12600                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12601                 {
12602                         f = RSurf_FogVertex(v);
12603                         c2[0] = f;
12604                         c2[1] = f;
12605                         c2[2] = f;
12606                         c2[3] = 1;
12607                 }
12608         }
12609 }
12610
12611 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12612 {
12613         int i;
12614         float f;
12615         const float *v;
12616         const float *c;
12617         float *c2;
12618         if (!rsurface.passcolor4f)
12619                 return;
12620         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
12621         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12622         rsurface.passcolor4f_vertexbuffer = 0;
12623         rsurface.passcolor4f_bufferoffset = 0;
12624         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)
12625         {
12626                 f = RSurf_FogVertex(v);
12627                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12628                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12629                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12630                 c2[3] = c[3];
12631         }
12632 }
12633
12634 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12635 {
12636         int i;
12637         const float *c;
12638         float *c2;
12639         if (!rsurface.passcolor4f)
12640                 return;
12641         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
12642         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12643         rsurface.passcolor4f_vertexbuffer = 0;
12644         rsurface.passcolor4f_bufferoffset = 0;
12645         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12646         {
12647                 c2[0] = c[0] * r;
12648                 c2[1] = c[1] * g;
12649                 c2[2] = c[2] * b;
12650                 c2[3] = c[3] * a;
12651         }
12652 }
12653
12654 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12655 {
12656         int i;
12657         const float *c;
12658         float *c2;
12659         if (!rsurface.passcolor4f)
12660                 return;
12661         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
12662         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12663         rsurface.passcolor4f_vertexbuffer = 0;
12664         rsurface.passcolor4f_bufferoffset = 0;
12665         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12666         {
12667                 c2[0] = c[0] + r_refdef.scene.ambient;
12668                 c2[1] = c[1] + r_refdef.scene.ambient;
12669                 c2[2] = c[2] + r_refdef.scene.ambient;
12670                 c2[3] = c[3];
12671         }
12672 }
12673
12674 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12675 {
12676         // TODO: optimize
12677         rsurface.passcolor4f = NULL;
12678         rsurface.passcolor4f_vertexbuffer = 0;
12679         rsurface.passcolor4f_bufferoffset = 0;
12680         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12681         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12682         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12683         GL_Color(r, g, b, a);
12684         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12685         RSurf_DrawBatch();
12686 }
12687
12688 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12689 {
12690         // TODO: optimize applyfog && applycolor case
12691         // just apply fog if necessary, and tint the fog color array if necessary
12692         rsurface.passcolor4f = NULL;
12693         rsurface.passcolor4f_vertexbuffer = 0;
12694         rsurface.passcolor4f_bufferoffset = 0;
12695         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12696         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12697         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12698         GL_Color(r, g, b, a);
12699         RSurf_DrawBatch();
12700 }
12701
12702 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12703 {
12704         // TODO: optimize
12705         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12706         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12707         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12708         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12709         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12710         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12711         GL_Color(r, g, b, a);
12712         RSurf_DrawBatch();
12713 }
12714
12715 static void RSurf_DrawBatch_GL11_ClampColor(void)
12716 {
12717         int i;
12718         const float *c1;
12719         float *c2;
12720         if (!rsurface.passcolor4f)
12721                 return;
12722         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12723         {
12724                 c2[0] = bound(0.0f, c1[0], 1.0f);
12725                 c2[1] = bound(0.0f, c1[1], 1.0f);
12726                 c2[2] = bound(0.0f, c1[2], 1.0f);
12727                 c2[3] = bound(0.0f, c1[3], 1.0f);
12728         }
12729 }
12730
12731 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12732 {
12733         int i;
12734         float f;
12735         const float *v;
12736         const float *n;
12737         float *c;
12738         //vec3_t eyedir;
12739
12740         // fake shading
12741         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12742         rsurface.passcolor4f_vertexbuffer = 0;
12743         rsurface.passcolor4f_bufferoffset = 0;
12744         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)
12745         {
12746                 f = -DotProduct(r_refdef.view.forward, n);
12747                 f = max(0, f);
12748                 f = f * 0.85 + 0.15; // work around so stuff won't get black
12749                 f *= r_refdef.lightmapintensity;
12750                 Vector4Set(c, f, f, f, 1);
12751         }
12752 }
12753
12754 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12755 {
12756         RSurf_DrawBatch_GL11_ApplyFakeLight();
12757         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12758         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12759         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12760         GL_Color(r, g, b, a);
12761         RSurf_DrawBatch();
12762 }
12763
12764 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12765 {
12766         int i;
12767         float f;
12768         float alpha;
12769         const float *v;
12770         const float *n;
12771         float *c;
12772         vec3_t ambientcolor;
12773         vec3_t diffusecolor;
12774         vec3_t lightdir;
12775         // TODO: optimize
12776         // model lighting
12777         VectorCopy(rsurface.modellight_lightdir, lightdir);
12778         f = 0.5f * r_refdef.lightmapintensity;
12779         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12780         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12781         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12782         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12783         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12784         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12785         alpha = *a;
12786         if (VectorLength2(diffusecolor) > 0)
12787         {
12788                 // q3-style directional shading
12789                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12790                 rsurface.passcolor4f_vertexbuffer = 0;
12791                 rsurface.passcolor4f_bufferoffset = 0;
12792                 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)
12793                 {
12794                         if ((f = DotProduct(n, lightdir)) > 0)
12795                                 VectorMA(ambientcolor, f, diffusecolor, c);
12796                         else
12797                                 VectorCopy(ambientcolor, c);
12798                         c[3] = alpha;
12799                 }
12800                 *r = 1;
12801                 *g = 1;
12802                 *b = 1;
12803                 *a = 1;
12804                 *applycolor = false;
12805         }
12806         else
12807         {
12808                 *r = ambientcolor[0];
12809                 *g = ambientcolor[1];
12810                 *b = ambientcolor[2];
12811                 rsurface.passcolor4f = NULL;
12812                 rsurface.passcolor4f_vertexbuffer = 0;
12813                 rsurface.passcolor4f_bufferoffset = 0;
12814         }
12815 }
12816
12817 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12818 {
12819         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12820         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12821         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12822         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12823         GL_Color(r, g, b, a);
12824         RSurf_DrawBatch();
12825 }
12826
12827 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12828 {
12829         int i;
12830         float f;
12831         const float *v;
12832         float *c;
12833         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12834         {
12835                 f = 1 - RSurf_FogVertex(v);
12836                 c[0] = r;
12837                 c[1] = g;
12838                 c[2] = b;
12839                 c[3] = f * a;
12840         }
12841 }
12842
12843 void RSurf_SetupDepthAndCulling(void)
12844 {
12845         // submodels are biased to avoid z-fighting with world surfaces that they
12846         // may be exactly overlapping (avoids z-fighting artifacts on certain
12847         // doors and things in Quake maps)
12848         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12849         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12850         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12851         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12852 }
12853
12854 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12855 {
12856         // transparent sky would be ridiculous
12857         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12858                 return;
12859         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12860         skyrenderlater = true;
12861         RSurf_SetupDepthAndCulling();
12862         GL_DepthMask(true);
12863         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12864         // skymasking on them, and Quake3 never did sky masking (unlike
12865         // software Quake and software Quake2), so disable the sky masking
12866         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12867         // and skymasking also looks very bad when noclipping outside the
12868         // level, so don't use it then either.
12869         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12870         {
12871                 R_Mesh_ResetTextureState();
12872                 if (skyrendermasked)
12873                 {
12874                         R_SetupShader_DepthOrShadow();
12875                         // depth-only (masking)
12876                         GL_ColorMask(0,0,0,0);
12877                         // just to make sure that braindead drivers don't draw
12878                         // anything despite that colormask...
12879                         GL_BlendFunc(GL_ZERO, GL_ONE);
12880                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12881                         if (rsurface.batchvertex3fbuffer)
12882                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12883                         else
12884                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12885                 }
12886                 else
12887                 {
12888                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12889                         // fog sky
12890                         GL_BlendFunc(GL_ONE, GL_ZERO);
12891                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12892                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12893                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12894                 }
12895                 RSurf_DrawBatch();
12896                 if (skyrendermasked)
12897                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12898         }
12899         R_Mesh_ResetTextureState();
12900         GL_Color(1, 1, 1, 1);
12901 }
12902
12903 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12904 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12905 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12906 {
12907         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12908                 return;
12909         if (prepass)
12910         {
12911                 // render screenspace normalmap to texture
12912                 GL_DepthMask(true);
12913                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12914                 RSurf_DrawBatch();
12915                 return;
12916         }
12917
12918         // bind lightmap texture
12919
12920         // water/refraction/reflection/camera surfaces have to be handled specially
12921         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12922         {
12923                 int start, end, startplaneindex;
12924                 for (start = 0;start < texturenumsurfaces;start = end)
12925                 {
12926                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12927                         if(startplaneindex < 0)
12928                         {
12929                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12930                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12931                                 end = start + 1;
12932                                 continue;
12933                         }
12934                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12935                                 ;
12936                         // now that we have a batch using the same planeindex, render it
12937                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12938                         {
12939                                 // render water or distortion background
12940                                 GL_DepthMask(true);
12941                                 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));
12942                                 RSurf_DrawBatch();
12943                                 // blend surface on top
12944                                 GL_DepthMask(false);
12945                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12946                                 RSurf_DrawBatch();
12947                         }
12948                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12949                         {
12950                                 // render surface with reflection texture as input
12951                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12952                                 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));
12953                                 RSurf_DrawBatch();
12954                         }
12955                 }
12956                 return;
12957         }
12958
12959         // render surface batch normally
12960         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12961         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12962         RSurf_DrawBatch();
12963 }
12964
12965 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12966 {
12967         // OpenGL 1.3 path - anything not completely ancient
12968         qboolean applycolor;
12969         qboolean applyfog;
12970         int layerindex;
12971         const texturelayer_t *layer;
12972         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);
12973         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12974
12975         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12976         {
12977                 vec4_t layercolor;
12978                 int layertexrgbscale;
12979                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12980                 {
12981                         if (layerindex == 0)
12982                                 GL_AlphaTest(true);
12983                         else
12984                         {
12985                                 GL_AlphaTest(false);
12986                                 GL_DepthFunc(GL_EQUAL);
12987                         }
12988                 }
12989                 GL_DepthMask(layer->depthmask && writedepth);
12990                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12991                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12992                 {
12993                         layertexrgbscale = 4;
12994                         VectorScale(layer->color, 0.25f, layercolor);
12995                 }
12996                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12997                 {
12998                         layertexrgbscale = 2;
12999                         VectorScale(layer->color, 0.5f, layercolor);
13000                 }
13001                 else
13002                 {
13003                         layertexrgbscale = 1;
13004                         VectorScale(layer->color, 1.0f, layercolor);
13005                 }
13006                 layercolor[3] = layer->color[3];
13007                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
13008                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
13009                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
13010                 switch (layer->type)
13011                 {
13012                 case TEXTURELAYERTYPE_LITTEXTURE:
13013                         // single-pass lightmapped texture with 2x rgbscale
13014                         R_Mesh_TexBind(0, r_texture_white);
13015                         R_Mesh_TexMatrix(0, NULL);
13016                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
13017                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
13018                         R_Mesh_TexBind(1, layer->texture);
13019                         R_Mesh_TexMatrix(1, &layer->texmatrix);
13020                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
13021                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
13022                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
13023                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
13024                         else if (FAKELIGHT_ENABLED)
13025                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
13026                         else if (rsurface.uselightmaptexture)
13027                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
13028                         else
13029                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
13030                         break;
13031                 case TEXTURELAYERTYPE_TEXTURE:
13032                         // singletexture unlit texture with transparency support
13033                         R_Mesh_TexBind(0, layer->texture);
13034                         R_Mesh_TexMatrix(0, &layer->texmatrix);
13035                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
13036                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
13037                         R_Mesh_TexBind(1, 0);
13038                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
13039                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
13040                         break;
13041                 case TEXTURELAYERTYPE_FOG:
13042                         // singletexture fogging
13043                         if (layer->texture)
13044                         {
13045                                 R_Mesh_TexBind(0, layer->texture);
13046                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
13047                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
13048                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
13049                         }
13050                         else
13051                         {
13052                                 R_Mesh_TexBind(0, 0);
13053                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
13054                         }
13055                         R_Mesh_TexBind(1, 0);
13056                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
13057                         // generate a color array for the fog pass
13058                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
13059                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
13060                         RSurf_DrawBatch();
13061                         break;
13062                 default:
13063                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
13064                 }
13065         }
13066         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
13067         {
13068                 GL_DepthFunc(GL_LEQUAL);
13069                 GL_AlphaTest(false);
13070         }
13071 }
13072
13073 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
13074 {
13075         // OpenGL 1.1 - crusty old voodoo path
13076         qboolean applyfog;
13077         int layerindex;
13078         const texturelayer_t *layer;
13079         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);
13080         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
13081
13082         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
13083         {
13084                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
13085                 {
13086                         if (layerindex == 0)
13087                                 GL_AlphaTest(true);
13088                         else
13089                         {
13090                                 GL_AlphaTest(false);
13091                                 GL_DepthFunc(GL_EQUAL);
13092                         }
13093                 }
13094                 GL_DepthMask(layer->depthmask && writedepth);
13095                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
13096                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
13097                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
13098                 switch (layer->type)
13099                 {
13100                 case TEXTURELAYERTYPE_LITTEXTURE:
13101                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
13102                         {
13103                                 // two-pass lit texture with 2x rgbscale
13104                                 // first the lightmap pass
13105                                 R_Mesh_TexBind(0, r_texture_white);
13106                                 R_Mesh_TexMatrix(0, NULL);
13107                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
13108                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
13109                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
13110                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
13111                                 else if (FAKELIGHT_ENABLED)
13112                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
13113                                 else if (rsurface.uselightmaptexture)
13114                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
13115                                 else
13116                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
13117                                 // then apply the texture to it
13118                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
13119                                 R_Mesh_TexBind(0, layer->texture);
13120                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
13121                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
13122                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
13123                                 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);
13124                         }
13125                         else
13126                         {
13127                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
13128                                 R_Mesh_TexBind(0, layer->texture);
13129                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
13130                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
13131                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
13132                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
13133                                         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);
13134                                 else
13135                                         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);
13136                         }
13137                         break;
13138                 case TEXTURELAYERTYPE_TEXTURE:
13139                         // singletexture unlit texture with transparency support
13140                         R_Mesh_TexBind(0, layer->texture);
13141                         R_Mesh_TexMatrix(0, &layer->texmatrix);
13142                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
13143                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
13144                         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);
13145                         break;
13146                 case TEXTURELAYERTYPE_FOG:
13147                         // singletexture fogging
13148                         if (layer->texture)
13149                         {
13150                                 R_Mesh_TexBind(0, layer->texture);
13151                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
13152                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
13153                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
13154                         }
13155                         else
13156                         {
13157                                 R_Mesh_TexBind(0, 0);
13158                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
13159                         }
13160                         // generate a color array for the fog pass
13161                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
13162                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
13163                         RSurf_DrawBatch();
13164                         break;
13165                 default:
13166                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
13167                 }
13168         }
13169         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
13170         {
13171                 GL_DepthFunc(GL_LEQUAL);
13172                 GL_AlphaTest(false);
13173         }
13174 }
13175
13176 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
13177 {
13178         int vi;
13179         int j;
13180         r_vertexgeneric_t *batchvertex;
13181         float c[4];
13182
13183         GL_AlphaTest(false);
13184 //      R_Mesh_ResetTextureState();
13185         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13186
13187         if(rsurface.texture && rsurface.texture->currentskinframe)
13188         {
13189                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
13190                 c[3] *= rsurface.texture->currentalpha;
13191         }
13192         else
13193         {
13194                 c[0] = 1;
13195                 c[1] = 0;
13196                 c[2] = 1;
13197                 c[3] = 1;
13198         }
13199
13200         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
13201         {
13202                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
13203                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
13204                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
13205         }
13206
13207         // brighten it up (as texture value 127 means "unlit")
13208         c[0] *= 2 * r_refdef.view.colorscale;
13209         c[1] *= 2 * r_refdef.view.colorscale;
13210         c[2] *= 2 * r_refdef.view.colorscale;
13211
13212         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
13213                 c[3] *= r_wateralpha.value;
13214
13215         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
13216         {
13217                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13218                 GL_DepthMask(false);
13219         }
13220         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
13221         {
13222                 GL_BlendFunc(GL_ONE, GL_ONE);
13223                 GL_DepthMask(false);
13224         }
13225         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
13226         {
13227                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
13228                 GL_DepthMask(false);
13229         }
13230         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
13231         {
13232                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
13233                 GL_DepthMask(false);
13234         }
13235         else
13236         {
13237                 GL_BlendFunc(GL_ONE, GL_ZERO);
13238                 GL_DepthMask(writedepth);
13239         }
13240
13241         if (r_showsurfaces.integer == 3)
13242         {
13243                 rsurface.passcolor4f = NULL;
13244
13245                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
13246                 {
13247                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13248
13249                         rsurface.passcolor4f = NULL;
13250                         rsurface.passcolor4f_vertexbuffer = 0;
13251                         rsurface.passcolor4f_bufferoffset = 0;
13252                 }
13253                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
13254                 {
13255                         qboolean applycolor = true;
13256                         float one = 1.0;
13257
13258                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13259
13260                         r_refdef.lightmapintensity = 1;
13261                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
13262                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
13263                 }
13264                 else if (FAKELIGHT_ENABLED)
13265                 {
13266                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13267
13268                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
13269                         RSurf_DrawBatch_GL11_ApplyFakeLight();
13270                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
13271                 }
13272                 else
13273                 {
13274                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13275
13276                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
13277                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
13278                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
13279                 }
13280
13281                 if(!rsurface.passcolor4f)
13282                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
13283
13284                 RSurf_DrawBatch_GL11_ApplyAmbient();
13285                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
13286                 if(r_refdef.fogenabled)
13287                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
13288                 RSurf_DrawBatch_GL11_ClampColor();
13289
13290                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
13291                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13292                 RSurf_DrawBatch();
13293         }
13294         else if (!r_refdef.view.showdebug)
13295         {
13296                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13297                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13298                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13299                 {
13300                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13301                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
13302                 }
13303                 R_Mesh_PrepareVertices_Generic_Unlock();
13304                 RSurf_DrawBatch();
13305         }
13306         else if (r_showsurfaces.integer == 4)
13307         {
13308                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13309                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13310                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13311                 {
13312                         unsigned char c = vi << 3;
13313                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13314                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
13315                 }
13316                 R_Mesh_PrepareVertices_Generic_Unlock();
13317                 RSurf_DrawBatch();
13318         }
13319         else if (r_showsurfaces.integer == 2)
13320         {
13321                 const int *e;
13322                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13323                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
13324                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
13325                 {
13326                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
13327                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
13328                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
13329                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
13330                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
13331                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
13332                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
13333                 }
13334                 R_Mesh_PrepareVertices_Generic_Unlock();
13335                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
13336         }
13337         else
13338         {
13339                 int texturesurfaceindex;
13340                 int k;
13341                 const msurface_t *surface;
13342                 unsigned char surfacecolor4ub[4];
13343                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13344                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
13345                 vi = 0;
13346                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
13347                 {
13348                         surface = texturesurfacelist[texturesurfaceindex];
13349                         k = (int)(((size_t)surface) / sizeof(msurface_t));
13350                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
13351                         for (j = 0;j < surface->num_vertices;j++)
13352                         {
13353                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13354                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
13355                                 vi++;
13356                         }
13357                 }
13358                 R_Mesh_PrepareVertices_Generic_Unlock();
13359                 RSurf_DrawBatch();
13360         }
13361 }
13362
13363 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13364 {
13365         CHECKGLERROR
13366         RSurf_SetupDepthAndCulling();
13367         if (r_showsurfaces.integer)
13368         {
13369                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13370                 return;
13371         }
13372         switch (vid.renderpath)
13373         {
13374         case RENDERPATH_GL20:
13375         case RENDERPATH_CGGL:
13376         case RENDERPATH_D3D9:
13377         case RENDERPATH_D3D10:
13378         case RENDERPATH_D3D11:
13379         case RENDERPATH_SOFT:
13380         case RENDERPATH_GLES2:
13381                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13382                 break;
13383         case RENDERPATH_GL13:
13384                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13385                 break;
13386         case RENDERPATH_GL11:
13387                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13388                 break;
13389         }
13390         CHECKGLERROR
13391 }
13392
13393 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13394 {
13395         CHECKGLERROR
13396         RSurf_SetupDepthAndCulling();
13397         if (r_showsurfaces.integer)
13398         {
13399                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13400                 return;
13401         }
13402         switch (vid.renderpath)
13403         {
13404         case RENDERPATH_GL20:
13405         case RENDERPATH_CGGL:
13406         case RENDERPATH_D3D9:
13407         case RENDERPATH_D3D10:
13408         case RENDERPATH_D3D11:
13409         case RENDERPATH_SOFT:
13410         case RENDERPATH_GLES2:
13411                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13412                 break;
13413         case RENDERPATH_GL13:
13414                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13415                 break;
13416         case RENDERPATH_GL11:
13417                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13418                 break;
13419         }
13420         CHECKGLERROR
13421 }
13422
13423 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13424 {
13425         int i, j;
13426         int texturenumsurfaces, endsurface;
13427         texture_t *texture;
13428         const msurface_t *surface;
13429 #define MAXBATCH_TRANSPARENTSURFACES 256
13430         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13431
13432         // if the model is static it doesn't matter what value we give for
13433         // wantnormals and wanttangents, so this logic uses only rules applicable
13434         // to a model, knowing that they are meaningless otherwise
13435         if (ent == r_refdef.scene.worldentity)
13436                 RSurf_ActiveWorldEntity();
13437         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13438                 RSurf_ActiveModelEntity(ent, false, false, false);
13439         else
13440         {
13441                 switch (vid.renderpath)
13442                 {
13443                 case RENDERPATH_GL20:
13444                 case RENDERPATH_CGGL:
13445                 case RENDERPATH_D3D9:
13446                 case RENDERPATH_D3D10:
13447                 case RENDERPATH_D3D11:
13448                 case RENDERPATH_SOFT:
13449                 case RENDERPATH_GLES2:
13450                         RSurf_ActiveModelEntity(ent, true, true, false);
13451                         break;
13452                 case RENDERPATH_GL13:
13453                 case RENDERPATH_GL11:
13454                         RSurf_ActiveModelEntity(ent, true, false, false);
13455                         break;
13456                 }
13457         }
13458
13459         if (r_transparentdepthmasking.integer)
13460         {
13461                 qboolean setup = false;
13462                 for (i = 0;i < numsurfaces;i = j)
13463                 {
13464                         j = i + 1;
13465                         surface = rsurface.modelsurfaces + surfacelist[i];
13466                         texture = surface->texture;
13467                         rsurface.texture = R_GetCurrentTexture(texture);
13468                         rsurface.lightmaptexture = NULL;
13469                         rsurface.deluxemaptexture = NULL;
13470                         rsurface.uselightmaptexture = false;
13471                         // scan ahead until we find a different texture
13472                         endsurface = min(i + 1024, numsurfaces);
13473                         texturenumsurfaces = 0;
13474                         texturesurfacelist[texturenumsurfaces++] = surface;
13475                         for (;j < endsurface;j++)
13476                         {
13477                                 surface = rsurface.modelsurfaces + surfacelist[j];
13478                                 if (texture != surface->texture)
13479                                         break;
13480                                 texturesurfacelist[texturenumsurfaces++] = surface;
13481                         }
13482                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13483                                 continue;
13484                         // render the range of surfaces as depth
13485                         if (!setup)
13486                         {
13487                                 setup = true;
13488                                 GL_ColorMask(0,0,0,0);
13489                                 GL_Color(1,1,1,1);
13490                                 GL_DepthTest(true);
13491                                 GL_BlendFunc(GL_ONE, GL_ZERO);
13492                                 GL_DepthMask(true);
13493                                 GL_AlphaTest(false);
13494 //                              R_Mesh_ResetTextureState();
13495                                 R_SetupShader_DepthOrShadow();
13496                         }
13497                         RSurf_SetupDepthAndCulling();
13498                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
13499                         if (rsurface.batchvertex3fbuffer)
13500                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
13501                         else
13502                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
13503                         RSurf_DrawBatch();
13504                 }
13505                 if (setup)
13506                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13507         }
13508
13509         for (i = 0;i < numsurfaces;i = j)
13510         {
13511                 j = i + 1;
13512                 surface = rsurface.modelsurfaces + surfacelist[i];
13513                 texture = surface->texture;
13514                 rsurface.texture = R_GetCurrentTexture(texture);
13515                 // scan ahead until we find a different texture
13516                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13517                 texturenumsurfaces = 0;
13518                 texturesurfacelist[texturenumsurfaces++] = surface;
13519                 if(FAKELIGHT_ENABLED)
13520                 {
13521                         rsurface.lightmaptexture = NULL;
13522                         rsurface.deluxemaptexture = NULL;
13523                         rsurface.uselightmaptexture = false;
13524                         for (;j < endsurface;j++)
13525                         {
13526                                 surface = rsurface.modelsurfaces + surfacelist[j];
13527                                 if (texture != surface->texture)
13528                                         break;
13529                                 texturesurfacelist[texturenumsurfaces++] = surface;
13530                         }
13531                 }
13532                 else
13533                 {
13534                         rsurface.lightmaptexture = surface->lightmaptexture;
13535                         rsurface.deluxemaptexture = surface->deluxemaptexture;
13536                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13537                         for (;j < endsurface;j++)
13538                         {
13539                                 surface = rsurface.modelsurfaces + surfacelist[j];
13540                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13541                                         break;
13542                                 texturesurfacelist[texturenumsurfaces++] = surface;
13543                         }
13544                 }
13545                 // render the range of surfaces
13546                 if (ent == r_refdef.scene.worldentity)
13547                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13548                 else
13549                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13550         }
13551         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13552         GL_AlphaTest(false);
13553 }
13554
13555 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13556 {
13557         // transparent surfaces get pushed off into the transparent queue
13558         int surfacelistindex;
13559         const msurface_t *surface;
13560         vec3_t tempcenter, center;
13561         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13562         {
13563                 surface = texturesurfacelist[surfacelistindex];
13564                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13565                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13566                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13567                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13568                 if (queueentity->transparent_offset) // transparent offset
13569                 {
13570                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13571                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13572                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13573                 }
13574                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13575         }
13576 }
13577
13578 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13579 {
13580         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13581                 return;
13582         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13583                 return;
13584         RSurf_SetupDepthAndCulling();
13585         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
13586         if (rsurface.batchvertex3fbuffer)
13587                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
13588         else
13589                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
13590         RSurf_DrawBatch();
13591 }
13592
13593 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13594 {
13595         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13596         CHECKGLERROR
13597         if (depthonly)
13598                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13599         else if (prepass)
13600         {
13601                 if (!rsurface.texture->currentnumlayers)
13602                         return;
13603                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13604                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13605                 else
13606                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13607         }
13608         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13609                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13610         else if (!rsurface.texture->currentnumlayers)
13611                 return;
13612         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13613         {
13614                 // in the deferred case, transparent surfaces were queued during prepass
13615                 if (!r_shadow_usingdeferredprepass)
13616                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13617         }
13618         else
13619         {
13620                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13621                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13622         }
13623         CHECKGLERROR
13624 }
13625
13626 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13627 {
13628         int i, j;
13629         texture_t *texture;
13630         R_FrameData_SetMark();
13631         // break the surface list down into batches by texture and use of lightmapping
13632         for (i = 0;i < numsurfaces;i = j)
13633         {
13634                 j = i + 1;
13635                 // texture is the base texture pointer, rsurface.texture is the
13636                 // current frame/skin the texture is directing us to use (for example
13637                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13638                 // use skin 1 instead)
13639                 texture = surfacelist[i]->texture;
13640                 rsurface.texture = R_GetCurrentTexture(texture);
13641                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13642                 {
13643                         // if this texture is not the kind we want, skip ahead to the next one
13644                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13645                                 ;
13646                         continue;
13647                 }
13648                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13649                 {
13650                         rsurface.lightmaptexture = NULL;
13651                         rsurface.deluxemaptexture = NULL;
13652                         rsurface.uselightmaptexture = false;
13653                         // simply scan ahead until we find a different texture or lightmap state
13654                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13655                                 ;
13656                 }
13657                 else
13658                 {
13659                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13660                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13661                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13662                         // simply scan ahead until we find a different texture or lightmap state
13663                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13664                                 ;
13665                 }
13666                 // render the range of surfaces
13667                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13668         }
13669         R_FrameData_ReturnToMark();
13670 }
13671
13672 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13673 {
13674         CHECKGLERROR
13675         if (depthonly)
13676                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13677         else if (prepass)
13678         {
13679                 if (!rsurface.texture->currentnumlayers)
13680                         return;
13681                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13682                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13683                 else
13684                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13685         }
13686         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13687                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13688         else if (!rsurface.texture->currentnumlayers)
13689                 return;
13690         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13691         {
13692                 // in the deferred case, transparent surfaces were queued during prepass
13693                 if (!r_shadow_usingdeferredprepass)
13694                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13695         }
13696         else
13697         {
13698                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13699                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13700         }
13701         CHECKGLERROR
13702 }
13703
13704 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13705 {
13706         int i, j;
13707         texture_t *texture;
13708         R_FrameData_SetMark();
13709         // break the surface list down into batches by texture and use of lightmapping
13710         for (i = 0;i < numsurfaces;i = j)
13711         {
13712                 j = i + 1;
13713                 // texture is the base texture pointer, rsurface.texture is the
13714                 // current frame/skin the texture is directing us to use (for example
13715                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13716                 // use skin 1 instead)
13717                 texture = surfacelist[i]->texture;
13718                 rsurface.texture = R_GetCurrentTexture(texture);
13719                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13720                 {
13721                         // if this texture is not the kind we want, skip ahead to the next one
13722                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13723                                 ;
13724                         continue;
13725                 }
13726                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13727                 {
13728                         rsurface.lightmaptexture = NULL;
13729                         rsurface.deluxemaptexture = NULL;
13730                         rsurface.uselightmaptexture = false;
13731                         // simply scan ahead until we find a different texture or lightmap state
13732                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13733                                 ;
13734                 }
13735                 else
13736                 {
13737                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13738                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13739                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13740                         // simply scan ahead until we find a different texture or lightmap state
13741                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13742                                 ;
13743                 }
13744                 // render the range of surfaces
13745                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13746         }
13747         R_FrameData_ReturnToMark();
13748 }
13749
13750 float locboxvertex3f[6*4*3] =
13751 {
13752         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13753         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13754         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13755         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13756         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13757         1,0,0, 0,0,0, 0,1,0, 1,1,0
13758 };
13759
13760 unsigned short locboxelements[6*2*3] =
13761 {
13762          0, 1, 2, 0, 2, 3,
13763          4, 5, 6, 4, 6, 7,
13764          8, 9,10, 8,10,11,
13765         12,13,14, 12,14,15,
13766         16,17,18, 16,18,19,
13767         20,21,22, 20,22,23
13768 };
13769
13770 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13771 {
13772         int i, j;
13773         cl_locnode_t *loc = (cl_locnode_t *)ent;
13774         vec3_t mins, size;
13775         float vertex3f[6*4*3];
13776         CHECKGLERROR
13777         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13778         GL_DepthMask(false);
13779         GL_DepthRange(0, 1);
13780         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13781         GL_DepthTest(true);
13782         GL_CullFace(GL_NONE);
13783         R_EntityMatrix(&identitymatrix);
13784
13785 //      R_Mesh_ResetTextureState();
13786
13787         i = surfacelist[0];
13788         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13789                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13790                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13791                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13792
13793         if (VectorCompare(loc->mins, loc->maxs))
13794         {
13795                 VectorSet(size, 2, 2, 2);
13796                 VectorMA(loc->mins, -0.5f, size, mins);
13797         }
13798         else
13799         {
13800                 VectorCopy(loc->mins, mins);
13801                 VectorSubtract(loc->maxs, loc->mins, size);
13802         }
13803
13804         for (i = 0;i < 6*4*3;)
13805                 for (j = 0;j < 3;j++, i++)
13806                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13807
13808         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13809         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13810         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13811 }
13812
13813 void R_DrawLocs(void)
13814 {
13815         int index;
13816         cl_locnode_t *loc, *nearestloc;
13817         vec3_t center;
13818         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13819         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13820         {
13821                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13822                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13823         }
13824 }
13825
13826 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13827 {
13828         if (decalsystem->decals)
13829                 Mem_Free(decalsystem->decals);
13830         memset(decalsystem, 0, sizeof(*decalsystem));
13831 }
13832
13833 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)
13834 {
13835         tridecal_t *decal;
13836         tridecal_t *decals;
13837         int i;
13838
13839         // expand or initialize the system
13840         if (decalsystem->maxdecals <= decalsystem->numdecals)
13841         {
13842                 decalsystem_t old = *decalsystem;
13843                 qboolean useshortelements;
13844                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13845                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13846                 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)));
13847                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13848                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13849                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13850                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13851                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13852                 if (decalsystem->numdecals)
13853                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13854                 if (old.decals)
13855                         Mem_Free(old.decals);
13856                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13857                         decalsystem->element3i[i] = i;
13858                 if (useshortelements)
13859                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13860                                 decalsystem->element3s[i] = i;
13861         }
13862
13863         // grab a decal and search for another free slot for the next one
13864         decals = decalsystem->decals;
13865         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13866         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13867                 ;
13868         decalsystem->freedecal = i;
13869         if (decalsystem->numdecals <= i)
13870                 decalsystem->numdecals = i + 1;
13871
13872         // initialize the decal
13873         decal->lived = 0;
13874         decal->triangleindex = triangleindex;
13875         decal->surfaceindex = surfaceindex;
13876         decal->decalsequence = decalsequence;
13877         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13878         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13879         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13880         decal->color4ub[0][3] = 255;
13881         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13882         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13883         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13884         decal->color4ub[1][3] = 255;
13885         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13886         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13887         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13888         decal->color4ub[2][3] = 255;
13889         decal->vertex3f[0][0] = v0[0];
13890         decal->vertex3f[0][1] = v0[1];
13891         decal->vertex3f[0][2] = v0[2];
13892         decal->vertex3f[1][0] = v1[0];
13893         decal->vertex3f[1][1] = v1[1];
13894         decal->vertex3f[1][2] = v1[2];
13895         decal->vertex3f[2][0] = v2[0];
13896         decal->vertex3f[2][1] = v2[1];
13897         decal->vertex3f[2][2] = v2[2];
13898         decal->texcoord2f[0][0] = t0[0];
13899         decal->texcoord2f[0][1] = t0[1];
13900         decal->texcoord2f[1][0] = t1[0];
13901         decal->texcoord2f[1][1] = t1[1];
13902         decal->texcoord2f[2][0] = t2[0];
13903         decal->texcoord2f[2][1] = t2[1];
13904 }
13905
13906 extern cvar_t cl_decals_bias;
13907 extern cvar_t cl_decals_models;
13908 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13909 // baseparms, parms, temps
13910 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)
13911 {
13912         int cornerindex;
13913         int index;
13914         float v[9][3];
13915         const float *vertex3f;
13916         int numpoints;
13917         float points[2][9][3];
13918         float temp[3];
13919         float tc[9][2];
13920         float f;
13921         float c[9][4];
13922         const int *e;
13923
13924         e = rsurface.modelelement3i + 3*triangleindex;
13925
13926         vertex3f = rsurface.modelvertex3f;
13927
13928         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13929         {
13930                 index = 3*e[cornerindex];
13931                 VectorCopy(vertex3f + index, v[cornerindex]);
13932         }
13933         // cull backfaces
13934         //TriangleNormal(v[0], v[1], v[2], normal);
13935         //if (DotProduct(normal, localnormal) < 0.0f)
13936         //      continue;
13937         // clip by each of the box planes formed from the projection matrix
13938         // if anything survives, we emit the decal
13939         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]);
13940         if (numpoints < 3)
13941                 return;
13942         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]);
13943         if (numpoints < 3)
13944                 return;
13945         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]);
13946         if (numpoints < 3)
13947                 return;
13948         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]);
13949         if (numpoints < 3)
13950                 return;
13951         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]);
13952         if (numpoints < 3)
13953                 return;
13954         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]);
13955         if (numpoints < 3)
13956                 return;
13957         // some part of the triangle survived, so we have to accept it...
13958         if (dynamic)
13959         {
13960                 // dynamic always uses the original triangle
13961                 numpoints = 3;
13962                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13963                 {
13964                         index = 3*e[cornerindex];
13965                         VectorCopy(vertex3f + index, v[cornerindex]);
13966                 }
13967         }
13968         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13969         {
13970                 // convert vertex positions to texcoords
13971                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13972                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13973                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13974                 // calculate distance fade from the projection origin
13975                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13976                 f = bound(0.0f, f, 1.0f);
13977                 c[cornerindex][0] = r * f;
13978                 c[cornerindex][1] = g * f;
13979                 c[cornerindex][2] = b * f;
13980                 c[cornerindex][3] = 1.0f;
13981                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13982         }
13983         if (dynamic)
13984                 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);
13985         else
13986                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13987                         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);
13988 }
13989 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)
13990 {
13991         matrix4x4_t projection;
13992         decalsystem_t *decalsystem;
13993         qboolean dynamic;
13994         dp_model_t *model;
13995         const msurface_t *surface;
13996         const msurface_t *surfaces;
13997         const int *surfacelist;
13998         const texture_t *texture;
13999         int numtriangles;
14000         int numsurfacelist;
14001         int surfacelistindex;
14002         int surfaceindex;
14003         int triangleindex;
14004         float localorigin[3];
14005         float localnormal[3];
14006         float localmins[3];
14007         float localmaxs[3];
14008         float localsize;
14009         //float normal[3];
14010         float planes[6][4];
14011         float angles[3];
14012         bih_t *bih;
14013         int bih_triangles_count;
14014         int bih_triangles[256];
14015         int bih_surfaces[256];
14016
14017         decalsystem = &ent->decalsystem;
14018         model = ent->model;
14019         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
14020         {
14021                 R_DecalSystem_Reset(&ent->decalsystem);
14022                 return;
14023         }
14024
14025         if (!model->brush.data_leafs && !cl_decals_models.integer)
14026         {
14027                 if (decalsystem->model)
14028                         R_DecalSystem_Reset(decalsystem);
14029                 return;
14030         }
14031
14032         if (decalsystem->model != model)
14033                 R_DecalSystem_Reset(decalsystem);
14034         decalsystem->model = model;
14035
14036         RSurf_ActiveModelEntity(ent, false, false, false);
14037
14038         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
14039         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
14040         VectorNormalize(localnormal);
14041         localsize = worldsize*rsurface.inversematrixscale;
14042         localmins[0] = localorigin[0] - localsize;
14043         localmins[1] = localorigin[1] - localsize;
14044         localmins[2] = localorigin[2] - localsize;
14045         localmaxs[0] = localorigin[0] + localsize;
14046         localmaxs[1] = localorigin[1] + localsize;
14047         localmaxs[2] = localorigin[2] + localsize;
14048
14049         //VectorCopy(localnormal, planes[4]);
14050         //VectorVectors(planes[4], planes[2], planes[0]);
14051         AnglesFromVectors(angles, localnormal, NULL, false);
14052         AngleVectors(angles, planes[0], planes[2], planes[4]);
14053         VectorNegate(planes[0], planes[1]);
14054         VectorNegate(planes[2], planes[3]);
14055         VectorNegate(planes[4], planes[5]);
14056         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
14057         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
14058         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
14059         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
14060         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
14061         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
14062
14063 #if 1
14064 // works
14065 {
14066         matrix4x4_t forwardprojection;
14067         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
14068         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
14069 }
14070 #else
14071 // broken
14072 {
14073         float projectionvector[4][3];
14074         VectorScale(planes[0], ilocalsize, projectionvector[0]);
14075         VectorScale(planes[2], ilocalsize, projectionvector[1]);
14076         VectorScale(planes[4], ilocalsize, projectionvector[2]);
14077         projectionvector[0][0] = planes[0][0] * ilocalsize;
14078         projectionvector[0][1] = planes[1][0] * ilocalsize;
14079         projectionvector[0][2] = planes[2][0] * ilocalsize;
14080         projectionvector[1][0] = planes[0][1] * ilocalsize;
14081         projectionvector[1][1] = planes[1][1] * ilocalsize;
14082         projectionvector[1][2] = planes[2][1] * ilocalsize;
14083         projectionvector[2][0] = planes[0][2] * ilocalsize;
14084         projectionvector[2][1] = planes[1][2] * ilocalsize;
14085         projectionvector[2][2] = planes[2][2] * ilocalsize;
14086         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
14087         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
14088         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
14089         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
14090 }
14091 #endif
14092
14093         dynamic = model->surfmesh.isanimated;
14094         numsurfacelist = model->nummodelsurfaces;
14095         surfacelist = model->sortedmodelsurfaces;
14096         surfaces = model->data_surfaces;
14097
14098         bih = NULL;
14099         bih_triangles_count = -1;
14100         if(!dynamic)
14101         {
14102                 if(model->render_bih.numleafs)
14103                         bih = &model->render_bih;
14104                 else if(model->collision_bih.numleafs)
14105                         bih = &model->collision_bih;
14106         }
14107         if(bih)
14108                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
14109         if(bih_triangles_count == 0)
14110                 return;
14111         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
14112                 return;
14113         if(bih_triangles_count > 0)
14114         {
14115                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
14116                 {
14117                         surfaceindex = bih_surfaces[triangleindex];
14118                         surface = surfaces + surfaceindex;
14119                         texture = surface->texture;
14120                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
14121                                 continue;
14122                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
14123                                 continue;
14124                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
14125                 }
14126         }
14127         else
14128         {
14129                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
14130                 {
14131                         surfaceindex = surfacelist[surfacelistindex];
14132                         surface = surfaces + surfaceindex;
14133                         // check cull box first because it rejects more than any other check
14134                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
14135                                 continue;
14136                         // skip transparent surfaces
14137                         texture = surface->texture;
14138                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
14139                                 continue;
14140                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
14141                                 continue;
14142                         numtriangles = surface->num_triangles;
14143                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
14144                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
14145                 }
14146         }
14147 }
14148
14149 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
14150 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)
14151 {
14152         int renderentityindex;
14153         float worldmins[3];
14154         float worldmaxs[3];
14155         entity_render_t *ent;
14156
14157         if (!cl_decals_newsystem.integer)
14158                 return;
14159
14160         worldmins[0] = worldorigin[0] - worldsize;
14161         worldmins[1] = worldorigin[1] - worldsize;
14162         worldmins[2] = worldorigin[2] - worldsize;
14163         worldmaxs[0] = worldorigin[0] + worldsize;
14164         worldmaxs[1] = worldorigin[1] + worldsize;
14165         worldmaxs[2] = worldorigin[2] + worldsize;
14166
14167         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
14168
14169         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
14170         {
14171                 ent = r_refdef.scene.entities[renderentityindex];
14172                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
14173                         continue;
14174
14175                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
14176         }
14177 }
14178
14179 typedef struct r_decalsystem_splatqueue_s
14180 {
14181         vec3_t worldorigin;
14182         vec3_t worldnormal;
14183         float color[4];
14184         float tcrange[4];
14185         float worldsize;
14186         int decalsequence;
14187 }
14188 r_decalsystem_splatqueue_t;
14189
14190 int r_decalsystem_numqueued = 0;
14191 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
14192
14193 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)
14194 {
14195         r_decalsystem_splatqueue_t *queue;
14196
14197         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
14198                 return;
14199
14200         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
14201         VectorCopy(worldorigin, queue->worldorigin);
14202         VectorCopy(worldnormal, queue->worldnormal);
14203         Vector4Set(queue->color, r, g, b, a);
14204         Vector4Set(queue->tcrange, s1, t1, s2, t2);
14205         queue->worldsize = worldsize;
14206         queue->decalsequence = cl.decalsequence++;
14207 }
14208
14209 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
14210 {
14211         int i;
14212         r_decalsystem_splatqueue_t *queue;
14213
14214         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
14215                 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);
14216         r_decalsystem_numqueued = 0;
14217 }
14218
14219 extern cvar_t cl_decals_max;
14220 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
14221 {
14222         int i;
14223         decalsystem_t *decalsystem = &ent->decalsystem;
14224         int numdecals;
14225         int killsequence;
14226         tridecal_t *decal;
14227         float frametime;
14228         float lifetime;
14229
14230         if (!decalsystem->numdecals)
14231                 return;
14232
14233         if (r_showsurfaces.integer)
14234                 return;
14235
14236         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
14237         {
14238                 R_DecalSystem_Reset(decalsystem);
14239                 return;
14240         }
14241
14242         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
14243         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
14244
14245         if (decalsystem->lastupdatetime)
14246                 frametime = (cl.time - decalsystem->lastupdatetime);
14247         else
14248                 frametime = 0;
14249         decalsystem->lastupdatetime = cl.time;
14250         decal = decalsystem->decals;
14251         numdecals = decalsystem->numdecals;
14252
14253         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14254         {
14255                 if (decal->color4ub[0][3])
14256                 {
14257                         decal->lived += frametime;
14258                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
14259                         {
14260                                 memset(decal, 0, sizeof(*decal));
14261                                 if (decalsystem->freedecal > i)
14262                                         decalsystem->freedecal = i;
14263                         }
14264                 }
14265         }
14266         decal = decalsystem->decals;
14267         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
14268                 numdecals--;
14269
14270         // collapse the array by shuffling the tail decals into the gaps
14271         for (;;)
14272         {
14273                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
14274                         decalsystem->freedecal++;
14275                 if (decalsystem->freedecal == numdecals)
14276                         break;
14277                 decal[decalsystem->freedecal] = decal[--numdecals];
14278         }
14279
14280         decalsystem->numdecals = numdecals;
14281
14282         if (numdecals <= 0)
14283         {
14284                 // if there are no decals left, reset decalsystem
14285                 R_DecalSystem_Reset(decalsystem);
14286         }
14287 }
14288
14289 extern skinframe_t *decalskinframe;
14290 static void R_DrawModelDecals_Entity(entity_render_t *ent)
14291 {
14292         int i;
14293         decalsystem_t *decalsystem = &ent->decalsystem;
14294         int numdecals;
14295         tridecal_t *decal;
14296         float faderate;
14297         float alpha;
14298         float *v3f;
14299         float *c4f;
14300         float *t2f;
14301         const int *e;
14302         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
14303         int numtris = 0;
14304
14305         numdecals = decalsystem->numdecals;
14306         if (!numdecals)
14307                 return;
14308
14309         if (r_showsurfaces.integer)
14310                 return;
14311
14312         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
14313         {
14314                 R_DecalSystem_Reset(decalsystem);
14315                 return;
14316         }
14317
14318         // if the model is static it doesn't matter what value we give for
14319         // wantnormals and wanttangents, so this logic uses only rules applicable
14320         // to a model, knowing that they are meaningless otherwise
14321         if (ent == r_refdef.scene.worldentity)
14322                 RSurf_ActiveWorldEntity();
14323         else
14324                 RSurf_ActiveModelEntity(ent, false, false, false);
14325
14326         decalsystem->lastupdatetime = cl.time;
14327         decal = decalsystem->decals;
14328
14329         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
14330
14331         // update vertex positions for animated models
14332         v3f = decalsystem->vertex3f;
14333         c4f = decalsystem->color4f;
14334         t2f = decalsystem->texcoord2f;
14335         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14336         {
14337                 if (!decal->color4ub[0][3])
14338                         continue;
14339
14340                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
14341                         continue;
14342
14343                 // update color values for fading decals
14344                 if (decal->lived >= cl_decals_time.value)
14345                 {
14346                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
14347                         alpha *= (1.0f/255.0f);
14348                 }
14349                 else
14350                         alpha = 1.0f/255.0f;
14351
14352                 c4f[ 0] = decal->color4ub[0][0] * alpha;
14353                 c4f[ 1] = decal->color4ub[0][1] * alpha;
14354                 c4f[ 2] = decal->color4ub[0][2] * alpha;
14355                 c4f[ 3] = 1;
14356                 c4f[ 4] = decal->color4ub[1][0] * alpha;
14357                 c4f[ 5] = decal->color4ub[1][1] * alpha;
14358                 c4f[ 6] = decal->color4ub[1][2] * alpha;
14359                 c4f[ 7] = 1;
14360                 c4f[ 8] = decal->color4ub[2][0] * alpha;
14361                 c4f[ 9] = decal->color4ub[2][1] * alpha;
14362                 c4f[10] = decal->color4ub[2][2] * alpha;
14363                 c4f[11] = 1;
14364
14365                 t2f[0] = decal->texcoord2f[0][0];
14366                 t2f[1] = decal->texcoord2f[0][1];
14367                 t2f[2] = decal->texcoord2f[1][0];
14368                 t2f[3] = decal->texcoord2f[1][1];
14369                 t2f[4] = decal->texcoord2f[2][0];
14370                 t2f[5] = decal->texcoord2f[2][1];
14371
14372                 // update vertex positions for animated models
14373                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
14374                 {
14375                         e = rsurface.modelelement3i + 3*decal->triangleindex;
14376                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
14377                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
14378                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
14379                 }
14380                 else
14381                 {
14382                         VectorCopy(decal->vertex3f[0], v3f);
14383                         VectorCopy(decal->vertex3f[1], v3f + 3);
14384                         VectorCopy(decal->vertex3f[2], v3f + 6);
14385                 }
14386
14387                 if (r_refdef.fogenabled)
14388                 {
14389                         alpha = RSurf_FogVertex(v3f);
14390                         VectorScale(c4f, alpha, c4f);
14391                         alpha = RSurf_FogVertex(v3f + 3);
14392                         VectorScale(c4f + 4, alpha, c4f + 4);
14393                         alpha = RSurf_FogVertex(v3f + 6);
14394                         VectorScale(c4f + 8, alpha, c4f + 8);
14395                 }
14396
14397                 v3f += 9;
14398                 c4f += 12;
14399                 t2f += 6;
14400                 numtris++;
14401         }
14402
14403         if (numtris > 0)
14404         {
14405                 r_refdef.stats.drawndecals += numtris;
14406
14407                 // now render the decals all at once
14408                 // (this assumes they all use one particle font texture!)
14409                 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);
14410 //              R_Mesh_ResetTextureState();
14411                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14412                 GL_DepthMask(false);
14413                 GL_DepthRange(0, 1);
14414                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14415                 GL_DepthTest(true);
14416                 GL_CullFace(GL_NONE);
14417                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14418                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14419                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14420         }
14421 }
14422
14423 static void R_DrawModelDecals(void)
14424 {
14425         int i, numdecals;
14426
14427         // fade faster when there are too many decals
14428         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14429         for (i = 0;i < r_refdef.scene.numentities;i++)
14430                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14431
14432         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14433         for (i = 0;i < r_refdef.scene.numentities;i++)
14434                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14435                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14436
14437         R_DecalSystem_ApplySplatEntitiesQueue();
14438
14439         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14440         for (i = 0;i < r_refdef.scene.numentities;i++)
14441                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14442
14443         r_refdef.stats.totaldecals += numdecals;
14444
14445         if (r_showsurfaces.integer)
14446                 return;
14447
14448         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14449
14450         for (i = 0;i < r_refdef.scene.numentities;i++)
14451         {
14452                 if (!r_refdef.viewcache.entityvisible[i])
14453                         continue;
14454                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14455                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14456         }
14457 }
14458
14459 extern cvar_t mod_collision_bih;
14460 void R_DrawDebugModel(void)
14461 {
14462         entity_render_t *ent = rsurface.entity;
14463         int i, j, k, l, flagsmask;
14464         const msurface_t *surface;
14465         dp_model_t *model = ent->model;
14466         vec3_t v;
14467
14468         switch(vid.renderpath)
14469         {
14470         case RENDERPATH_GL11:
14471         case RENDERPATH_GL13:
14472         case RENDERPATH_GL20:
14473         case RENDERPATH_CGGL:
14474                 break;
14475         case RENDERPATH_D3D9:
14476                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14477                 return;
14478         case RENDERPATH_D3D10:
14479                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14480                 return;
14481         case RENDERPATH_D3D11:
14482                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14483                 return;
14484         case RENDERPATH_SOFT:
14485                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14486                 return;
14487         case RENDERPATH_GLES2:
14488                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14489                 break;
14490         }
14491
14492         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14493
14494 //      R_Mesh_ResetTextureState();
14495         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14496         GL_DepthRange(0, 1);
14497         GL_DepthTest(!r_showdisabledepthtest.integer);
14498         GL_DepthMask(false);
14499         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14500
14501         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14502         {
14503                 int triangleindex;
14504                 int bihleafindex;
14505                 qboolean cullbox = ent == r_refdef.scene.worldentity;
14506                 const q3mbrush_t *brush;
14507                 const bih_t *bih = &model->collision_bih;
14508                 const bih_leaf_t *bihleaf;
14509                 float vertex3f[3][3];
14510                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14511                 cullbox = false;
14512                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14513                 {
14514                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14515                                 continue;
14516                         switch (bihleaf->type)
14517                         {
14518                         case BIH_BRUSH:
14519                                 brush = model->brush.data_brushes + bihleaf->itemindex;
14520                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
14521                                 {
14522                                         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);
14523                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14524                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14525                                 }
14526                                 break;
14527                         case BIH_COLLISIONTRIANGLE:
14528                                 triangleindex = bihleaf->itemindex;
14529                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14530                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14531                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14532                                 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);
14533                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14534                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14535                                 break;
14536                         case BIH_RENDERTRIANGLE:
14537                                 triangleindex = bihleaf->itemindex;
14538                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14539                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14540                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14541                                 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);
14542                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14543                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14544                                 break;
14545                         }
14546                 }
14547         }
14548
14549         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14550
14551         if (r_showtris.integer || (r_shownormals.value != 0))
14552         {
14553                 if (r_showdisabledepthtest.integer)
14554                 {
14555                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14556                         GL_DepthMask(false);
14557                 }
14558                 else
14559                 {
14560                         GL_BlendFunc(GL_ONE, GL_ZERO);
14561                         GL_DepthMask(true);
14562                 }
14563                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14564                 {
14565                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14566                                 continue;
14567                         rsurface.texture = R_GetCurrentTexture(surface->texture);
14568                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14569                         {
14570                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14571                                 if (r_showtris.value > 0)
14572                                 {
14573                                         if (!rsurface.texture->currentlayers->depthmask)
14574                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14575                                         else if (ent == r_refdef.scene.worldentity)
14576                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14577                                         else
14578                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14579                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14580                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14581                                         RSurf_DrawBatch();
14582                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14583                                         CHECKGLERROR
14584                                 }
14585                                 if (r_shownormals.value < 0)
14586                                 {
14587                                         qglBegin(GL_LINES);
14588                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14589                                         {
14590                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14591                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14592                                                 qglVertex3f(v[0], v[1], v[2]);
14593                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14594                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14595                                                 qglVertex3f(v[0], v[1], v[2]);
14596                                         }
14597                                         qglEnd();
14598                                         CHECKGLERROR
14599                                 }
14600                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14601                                 {
14602                                         qglBegin(GL_LINES);
14603                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14604                                         {
14605                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14606                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14607                                                 qglVertex3f(v[0], v[1], v[2]);
14608                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14609                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14610                                                 qglVertex3f(v[0], v[1], v[2]);
14611                                         }
14612                                         qglEnd();
14613                                         CHECKGLERROR
14614                                         qglBegin(GL_LINES);
14615                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14616                                         {
14617                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14618                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14619                                                 qglVertex3f(v[0], v[1], v[2]);
14620                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14621                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14622                                                 qglVertex3f(v[0], v[1], v[2]);
14623                                         }
14624                                         qglEnd();
14625                                         CHECKGLERROR
14626                                         qglBegin(GL_LINES);
14627                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14628                                         {
14629                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14630                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14631                                                 qglVertex3f(v[0], v[1], v[2]);
14632                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14633                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14634                                                 qglVertex3f(v[0], v[1], v[2]);
14635                                         }
14636                                         qglEnd();
14637                                         CHECKGLERROR
14638                                 }
14639                         }
14640                 }
14641                 rsurface.texture = NULL;
14642         }
14643 }
14644
14645 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14646 int r_maxsurfacelist = 0;
14647 const msurface_t **r_surfacelist = NULL;
14648 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14649 {
14650         int i, j, endj, flagsmask;
14651         dp_model_t *model = r_refdef.scene.worldmodel;
14652         msurface_t *surfaces;
14653         unsigned char *update;
14654         int numsurfacelist = 0;
14655         if (model == NULL)
14656                 return;
14657
14658         if (r_maxsurfacelist < model->num_surfaces)
14659         {
14660                 r_maxsurfacelist = model->num_surfaces;
14661                 if (r_surfacelist)
14662                         Mem_Free((msurface_t**)r_surfacelist);
14663                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14664         }
14665
14666         RSurf_ActiveWorldEntity();
14667
14668         surfaces = model->data_surfaces;
14669         update = model->brushq1.lightmapupdateflags;
14670
14671         // update light styles on this submodel
14672         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14673         {
14674                 model_brush_lightstyleinfo_t *style;
14675                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14676                 {
14677                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14678                         {
14679                                 int *list = style->surfacelist;
14680                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14681                                 for (j = 0;j < style->numsurfaces;j++)
14682                                         update[list[j]] = true;
14683                         }
14684                 }
14685         }
14686
14687         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14688
14689         if (debug)
14690         {
14691                 R_DrawDebugModel();
14692                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14693                 return;
14694         }
14695
14696         rsurface.lightmaptexture = NULL;
14697         rsurface.deluxemaptexture = NULL;
14698         rsurface.uselightmaptexture = false;
14699         rsurface.texture = NULL;
14700         rsurface.rtlight = NULL;
14701         numsurfacelist = 0;
14702         // add visible surfaces to draw list
14703         for (i = 0;i < model->nummodelsurfaces;i++)
14704         {
14705                 j = model->sortedmodelsurfaces[i];
14706                 if (r_refdef.viewcache.world_surfacevisible[j])
14707                         r_surfacelist[numsurfacelist++] = surfaces + j;
14708         }
14709         // update lightmaps if needed
14710         if (model->brushq1.firstrender)
14711         {
14712                 model->brushq1.firstrender = false;
14713                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14714                         if (update[j])
14715                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14716         }
14717         else if (update)
14718         {
14719                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14720                         if (r_refdef.viewcache.world_surfacevisible[j])
14721                                 if (update[j])
14722                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14723         }
14724         // don't do anything if there were no surfaces
14725         if (!numsurfacelist)
14726         {
14727                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14728                 return;
14729         }
14730         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14731         GL_AlphaTest(false);
14732
14733         // add to stats if desired
14734         if (r_speeds.integer && !skysurfaces && !depthonly)
14735         {
14736                 r_refdef.stats.world_surfaces += numsurfacelist;
14737                 for (j = 0;j < numsurfacelist;j++)
14738                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14739         }
14740
14741         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14742 }
14743
14744 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14745 {
14746         int i, j, endj, flagsmask;
14747         dp_model_t *model = ent->model;
14748         msurface_t *surfaces;
14749         unsigned char *update;
14750         int numsurfacelist = 0;
14751         if (model == NULL)
14752                 return;
14753
14754         if (r_maxsurfacelist < model->num_surfaces)
14755         {
14756                 r_maxsurfacelist = model->num_surfaces;
14757                 if (r_surfacelist)
14758                         Mem_Free((msurface_t **)r_surfacelist);
14759                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14760         }
14761
14762         // if the model is static it doesn't matter what value we give for
14763         // wantnormals and wanttangents, so this logic uses only rules applicable
14764         // to a model, knowing that they are meaningless otherwise
14765         if (ent == r_refdef.scene.worldentity)
14766                 RSurf_ActiveWorldEntity();
14767         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14768                 RSurf_ActiveModelEntity(ent, false, false, false);
14769         else if (prepass)
14770                 RSurf_ActiveModelEntity(ent, true, true, true);
14771         else if (depthonly)
14772         {
14773                 switch (vid.renderpath)
14774                 {
14775                 case RENDERPATH_GL20:
14776                 case RENDERPATH_CGGL:
14777                 case RENDERPATH_D3D9:
14778                 case RENDERPATH_D3D10:
14779                 case RENDERPATH_D3D11:
14780                 case RENDERPATH_SOFT:
14781                 case RENDERPATH_GLES2:
14782                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14783                         break;
14784                 case RENDERPATH_GL13:
14785                 case RENDERPATH_GL11:
14786                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14787                         break;
14788                 }
14789         }
14790         else
14791         {
14792                 switch (vid.renderpath)
14793                 {
14794                 case RENDERPATH_GL20:
14795                 case RENDERPATH_CGGL:
14796                 case RENDERPATH_D3D9:
14797                 case RENDERPATH_D3D10:
14798                 case RENDERPATH_D3D11:
14799                 case RENDERPATH_SOFT:
14800                 case RENDERPATH_GLES2:
14801                         RSurf_ActiveModelEntity(ent, true, true, false);
14802                         break;
14803                 case RENDERPATH_GL13:
14804                 case RENDERPATH_GL11:
14805                         RSurf_ActiveModelEntity(ent, true, false, false);
14806                         break;
14807                 }
14808         }
14809
14810         surfaces = model->data_surfaces;
14811         update = model->brushq1.lightmapupdateflags;
14812
14813         // update light styles
14814         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14815         {
14816                 model_brush_lightstyleinfo_t *style;
14817                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14818                 {
14819                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14820                         {
14821                                 int *list = style->surfacelist;
14822                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14823                                 for (j = 0;j < style->numsurfaces;j++)
14824                                         update[list[j]] = true;
14825                         }
14826                 }
14827         }
14828
14829         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14830
14831         if (debug)
14832         {
14833                 R_DrawDebugModel();
14834                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14835                 return;
14836         }
14837
14838         rsurface.lightmaptexture = NULL;
14839         rsurface.deluxemaptexture = NULL;
14840         rsurface.uselightmaptexture = false;
14841         rsurface.texture = NULL;
14842         rsurface.rtlight = NULL;
14843         numsurfacelist = 0;
14844         // add visible surfaces to draw list
14845         for (i = 0;i < model->nummodelsurfaces;i++)
14846                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14847         // don't do anything if there were no surfaces
14848         if (!numsurfacelist)
14849         {
14850                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14851                 return;
14852         }
14853         // update lightmaps if needed
14854         if (update)
14855         {
14856                 int updated = 0;
14857                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14858                 {
14859                         if (update[j])
14860                         {
14861                                 updated++;
14862                                 R_BuildLightMap(ent, surfaces + j);
14863                         }
14864                 }
14865         }
14866         if (update)
14867                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14868                         if (update[j])
14869                                 R_BuildLightMap(ent, surfaces + j);
14870         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14871         GL_AlphaTest(false);
14872
14873         // add to stats if desired
14874         if (r_speeds.integer && !skysurfaces && !depthonly)
14875         {
14876                 r_refdef.stats.entities_surfaces += numsurfacelist;
14877                 for (j = 0;j < numsurfacelist;j++)
14878                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14879         }
14880
14881         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14882 }
14883
14884 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14885 {
14886         static texture_t texture;
14887         static msurface_t surface;
14888         const msurface_t *surfacelist = &surface;
14889
14890         // fake enough texture and surface state to render this geometry
14891
14892         texture.update_lastrenderframe = -1; // regenerate this texture
14893         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14894         texture.currentskinframe = skinframe;
14895         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14896         texture.offsetmapping = OFFSETMAPPING_OFF;
14897         texture.offsetscale = 1;
14898         texture.specularscalemod = 1;
14899         texture.specularpowermod = 1;
14900
14901         surface.texture = &texture;
14902         surface.num_triangles = numtriangles;
14903         surface.num_firsttriangle = firsttriangle;
14904         surface.num_vertices = numvertices;
14905         surface.num_firstvertex = firstvertex;
14906
14907         // now render it
14908         rsurface.texture = R_GetCurrentTexture(surface.texture);
14909         rsurface.lightmaptexture = NULL;
14910         rsurface.deluxemaptexture = NULL;
14911         rsurface.uselightmaptexture = false;
14912         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14913 }
14914
14915 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)
14916 {
14917         static msurface_t surface;
14918         const msurface_t *surfacelist = &surface;
14919
14920         // fake enough texture and surface state to render this geometry
14921         surface.texture = texture;
14922         surface.num_triangles = numtriangles;
14923         surface.num_firsttriangle = firsttriangle;
14924         surface.num_vertices = numvertices;
14925         surface.num_firstvertex = firstvertex;
14926
14927         // now render it
14928         rsurface.texture = R_GetCurrentTexture(surface.texture);
14929         rsurface.lightmaptexture = NULL;
14930         rsurface.deluxemaptexture = NULL;
14931         rsurface.uselightmaptexture = false;
14932         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14933 }