]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
removed unmaintained CgGL rendering 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 "// GL ES shaders use precision modifiers, standard GL does not\n"
595 "#ifndef GL_ES\n"
596 "#define lowp\n"
597 "#define mediump\n"
598 "#define highp\n"
599 "#endif\n"
600 "\n"
601 "#ifdef VERTEX_SHADER\n"
602 "attribute vec4 Attrib_Position;  // vertex\n"
603 "attribute vec4 Attrib_Color;     // color\n"
604 "attribute vec4 Attrib_TexCoord0; // material texcoords\n"
605 "attribute vec3 Attrib_TexCoord1; // svector\n"
606 "attribute vec3 Attrib_TexCoord2; // tvector\n"
607 "attribute vec3 Attrib_TexCoord3; // normal\n"
608 "attribute vec4 Attrib_TexCoord4; // lightmap texcoords\n"
609 "#endif\n"
610 "varying lowp vec4 VertexColor;\n"
611 "\n"
612 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
613 "# define USEFOG\n"
614 "#endif\n"
615 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
616 "#define USELIGHTMAP\n"
617 "#endif\n"
618 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
619 "#define USEEYEVECTOR\n"
620 "#endif\n"
621 "\n"
622 "#ifdef USESHADOWMAP2D\n"
623 "# ifdef GL_EXT_gpu_shader4\n"
624 "#   extension GL_EXT_gpu_shader4 : enable\n"
625 "# endif\n"
626 "# ifdef GL_ARB_texture_gather\n"
627 "#   extension GL_ARB_texture_gather : enable\n"
628 "# else\n"
629 "#   ifdef GL_AMD_texture_texture4\n"
630 "#     extension GL_AMD_texture_texture4 : enable\n"
631 "#   endif\n"
632 "# endif\n"
633 "#endif\n"
634 "\n"
635 "//#ifdef USESHADOWSAMPLER\n"
636 "//# extension GL_ARB_shadow : enable\n"
637 "//#endif\n"
638 "\n"
639 "//#ifdef __GLSL_CG_DATA_TYPES\n"
640 "//# define myhalf half\n"
641 "//# define myhalf2 half2\n"
642 "//# define myhalf3 half3\n"
643 "//# define myhalf4 half4\n"
644 "//#else\n"
645 "# define myhalf mediump float\n"
646 "# define myhalf2 mediump vec2\n"
647 "# define myhalf3 mediump vec3\n"
648 "# define myhalf4 mediump vec4\n"
649 "//#endif\n"
650 "\n"
651 "#ifdef VERTEX_SHADER\n"
652 "uniform highp mat4 ModelViewProjectionMatrix;\n"
653 "#endif\n"
654 "\n"
655 "#ifdef MODE_DEPTH_OR_SHADOW\n"
656 "#ifdef VERTEX_SHADER\n"
657 "void main(void)\n"
658 "{\n"
659 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
660 "}\n"
661 "#endif\n"
662 "#else // !MODE_DEPTH_ORSHADOW\n"
663 "\n"
664 "\n"
665 "\n"
666 "\n"
667 "#ifdef MODE_SHOWDEPTH\n"
668 "#ifdef VERTEX_SHADER\n"
669 "void main(void)\n"
670 "{\n"
671 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
672 "       VertexColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
673 "}\n"
674 "#endif\n"
675 "\n"
676 "#ifdef FRAGMENT_SHADER\n"
677 "void main(void)\n"
678 "{\n"
679 "       gl_FragColor = VertexColor;\n"
680 "}\n"
681 "#endif\n"
682 "#else // !MODE_SHOWDEPTH\n"
683 "\n"
684 "\n"
685 "\n"
686 "\n"
687 "#ifdef MODE_POSTPROCESS\n"
688 "varying mediump vec2 TexCoord1;\n"
689 "varying mediump vec2 TexCoord2;\n"
690 "\n"
691 "#ifdef VERTEX_SHADER\n"
692 "void main(void)\n"
693 "{\n"
694 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
695 "       TexCoord1 = Attrib_TexCoord0.xy;\n"
696 "#ifdef USEBLOOM\n"
697 "       TexCoord2 = Attrib_TexCoord4.xy;\n"
698 "#endif\n"
699 "}\n"
700 "#endif\n"
701 "\n"
702 "#ifdef FRAGMENT_SHADER\n"
703 "uniform sampler2D Texture_First;\n"
704 "#ifdef USEBLOOM\n"
705 "uniform sampler2D Texture_Second;\n"
706 "uniform lowp vec4 BloomColorSubtract;\n"
707 "#endif\n"
708 "#ifdef USEGAMMARAMPS\n"
709 "uniform sampler2D Texture_GammaRamps;\n"
710 "#endif\n"
711 "#ifdef USESATURATION\n"
712 "uniform lowp float Saturation;\n"
713 "#endif\n"
714 "#ifdef USEVIEWTINT\n"
715 "uniform lowp vec4 ViewTintColor;\n"
716 "#endif\n"
717 "//uncomment these if you want to use them:\n"
718 "uniform mediump vec4 UserVec1;\n"
719 "uniform mediump vec4 UserVec2;\n"
720 "// uniform mediump vec4 UserVec3;\n"
721 "// uniform mediump vec4 UserVec4;\n"
722 "// uniform highp float ClientTime;\n"
723 "uniform mediump vec2 PixelSize;\n"
724 "void main(void)\n"
725 "{\n"
726 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
727 "#ifdef USEBLOOM\n"
728 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
729 "#endif\n"
730 "#ifdef USEVIEWTINT\n"
731 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
732 "#endif\n"
733 "\n"
734 "#ifdef USEPOSTPROCESSING\n"
735 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
736 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
737 "       float sobel = 1.0;\n"
738 "       // vec2 ts = textureSize(Texture_First, 0);\n"
739 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
740 "       vec2 px = PixelSize;\n"
741 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
742 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
743 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
744 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
745 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
746 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
747 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
748 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
749 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
750 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
751 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
752 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
753 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
754 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
755 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
756 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
757 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
758 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
759 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
760 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
761 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
762 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
763 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
764 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
765 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
766 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
767 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
768 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
769 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
770 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
771 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
772 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
773 "#endif\n"
774 "\n"
775 "#ifdef USESATURATION\n"
776 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
777 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
778 "       // 'vampire sight' effect, wheres red is compensated\n"
779 "       #ifdef SATURATION_REDCOMPENSATE\n"
780 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
781 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
782 "               gl_FragColor.r += rboost;\n"
783 "       #else\n"
784 "               // normal desaturation\n"
785 "               //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
786 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
787 "       #endif\n"
788 "#endif\n"
789 "\n"
790 "#ifdef USEGAMMARAMPS\n"
791 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
792 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
793 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
794 "#endif\n"
795 "}\n"
796 "#endif\n"
797 "#else // !MODE_POSTPROCESS\n"
798 "\n"
799 "\n"
800 "\n"
801 "\n"
802 "#ifdef MODE_GENERIC\n"
803 "#ifdef USEDIFFUSE\n"
804 "varying mediump vec2 TexCoord1;\n"
805 "#endif\n"
806 "#ifdef USESPECULAR\n"
807 "varying mediump vec2 TexCoord2;\n"
808 "#endif\n"
809 "#ifdef VERTEX_SHADER\n"
810 "void main(void)\n"
811 "{\n"
812 "       VertexColor = Attrib_Color;\n"
813 "#ifdef USEDIFFUSE\n"
814 "       TexCoord1 = Attrib_TexCoord0.xy;\n"
815 "#endif\n"
816 "#ifdef USESPECULAR\n"
817 "       TexCoord2 = Attrib_TexCoord1.xy;\n"
818 "#endif\n"
819 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
820 "}\n"
821 "#endif\n"
822 "\n"
823 "#ifdef FRAGMENT_SHADER\n"
824 "#ifdef USEDIFFUSE\n"
825 "uniform sampler2D Texture_First;\n"
826 "#endif\n"
827 "#ifdef USESPECULAR\n"
828 "uniform sampler2D Texture_Second;\n"
829 "#endif\n"
830 "\n"
831 "void main(void)\n"
832 "{\n"
833 "#ifdef USEVIEWTINT\n"
834 "       gl_FragColor = VertexColor;\n"
835 "#else\n"
836 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
837 "#endif\n"
838 "#ifdef USEDIFFUSE\n"
839 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
840 "#endif\n"
841 "\n"
842 "#ifdef USESPECULAR\n"
843 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
844 "# ifdef USECOLORMAPPING\n"
845 "       gl_FragColor *= tex2;\n"
846 "# endif\n"
847 "# ifdef USEGLOW\n"
848 "       gl_FragColor += tex2;\n"
849 "# endif\n"
850 "# ifdef USEVERTEXTEXTUREBLEND\n"
851 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
852 "# endif\n"
853 "#endif\n"
854 "}\n"
855 "#endif\n"
856 "#else // !MODE_GENERIC\n"
857 "\n"
858 "\n"
859 "\n"
860 "\n"
861 "#ifdef MODE_BLOOMBLUR\n"
862 "varying mediump vec2 TexCoord;\n"
863 "#ifdef VERTEX_SHADER\n"
864 "void main(void)\n"
865 "{\n"
866 "       VertexColor = Attrib_Color;\n"
867 "       TexCoord = Attrib_TexCoord0.xy;\n"
868 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
869 "}\n"
870 "#endif\n"
871 "\n"
872 "#ifdef FRAGMENT_SHADER\n"
873 "uniform sampler2D Texture_First;\n"
874 "uniform mediump vec4 BloomBlur_Parameters;\n"
875 "\n"
876 "void main(void)\n"
877 "{\n"
878 "       int i;\n"
879 "       vec2 tc = TexCoord;\n"
880 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
881 "       tc += BloomBlur_Parameters.xy;\n"
882 "       for (i = 1;i < SAMPLES;i++)\n"
883 "       {\n"
884 "               color += texture2D(Texture_First, tc).rgb;\n"
885 "               tc += BloomBlur_Parameters.xy;\n"
886 "       }\n"
887 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
888 "}\n"
889 "#endif\n"
890 "#else // !MODE_BLOOMBLUR\n"
891 "#ifdef MODE_REFRACTION\n"
892 "varying mediump vec2 TexCoord;\n"
893 "varying highp vec4 ModelViewProjectionPosition;\n"
894 "uniform highp mat4 TexMatrix;\n"
895 "#ifdef VERTEX_SHADER\n"
896 "\n"
897 "void main(void)\n"
898 "{\n"
899 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
900 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
901 "       ModelViewProjectionPosition = gl_Position;\n"
902 "}\n"
903 "#endif\n"
904 "\n"
905 "#ifdef FRAGMENT_SHADER\n"
906 "uniform sampler2D Texture_Normal;\n"
907 "uniform sampler2D Texture_Refraction;\n"
908 "uniform sampler2D Texture_Reflection;\n"
909 "\n"
910 "uniform mediump vec4 DistortScaleRefractReflect;\n"
911 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
912 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
913 "uniform lowp vec4 RefractColor;\n"
914 "uniform lowp vec4 ReflectColor;\n"
915 "uniform mediump float ReflectFactor;\n"
916 "uniform mediump float ReflectOffset;\n"
917 "\n"
918 "void main(void)\n"
919 "{\n"
920 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
921 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
922 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
923 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
924 "       // FIXME temporary hack to detect the case that the reflection\n"
925 "       // gets blackened at edges due to leaving the area that contains actual\n"
926 "       // content.\n"
927 "       // Remove this 'ack once we have a better way to stop this thing from\n"
928 "       // 'appening.\n"
929 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
930 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
931 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
932 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
933 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
934 "       gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
935 "}\n"
936 "#endif\n"
937 "#else // !MODE_REFRACTION\n"
938 "\n"
939 "\n"
940 "\n"
941 "\n"
942 "#ifdef MODE_WATER\n"
943 "varying mediump vec2 TexCoord;\n"
944 "varying highp vec3 EyeVector;\n"
945 "varying highp vec4 ModelViewProjectionPosition;\n"
946 "#ifdef VERTEX_SHADER\n"
947 "uniform highp vec3 EyePosition;\n"
948 "uniform highp mat4 TexMatrix;\n"
949 "\n"
950 "void main(void)\n"
951 "{\n"
952 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
953 "       vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
954 "       EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
955 "       EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
956 "       EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
957 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
958 "       ModelViewProjectionPosition = gl_Position;\n"
959 "}\n"
960 "#endif\n"
961 "\n"
962 "#ifdef FRAGMENT_SHADER\n"
963 "uniform sampler2D Texture_Normal;\n"
964 "uniform sampler2D Texture_Refraction;\n"
965 "uniform sampler2D Texture_Reflection;\n"
966 "\n"
967 "uniform mediump vec4 DistortScaleRefractReflect;\n"
968 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
969 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
970 "uniform lowp vec4 RefractColor;\n"
971 "uniform lowp vec4 ReflectColor;\n"
972 "uniform mediump float ReflectFactor;\n"
973 "uniform mediump float ReflectOffset;\n"
974 "uniform highp float ClientTime;\n"
975 "#ifdef USENORMALMAPSCROLLBLEND\n"
976 "uniform highp vec2 NormalmapScrollBlend;\n"
977 "#endif\n"
978 "\n"
979 "void main(void)\n"
980 "{\n"
981 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
982 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
983 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
984 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
985 "       // slight water animation via 2 layer scrolling (todo: tweak)\n"
986 "       #ifdef USENORMALMAPSCROLLBLEND\n"
987 "               vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
988 "               normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
989 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
990 "       #else\n"
991 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
992 "       #endif\n"
993 "       // FIXME temporary hack to detect the case that the reflection\n"
994 "       // gets blackened at edges due to leaving the area that contains actual\n"
995 "       // content.\n"
996 "       // Remove this 'ack once we have a better way to stop this thing from\n"
997 "       // 'appening.\n"
998 "       float f  = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
999 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
1000 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
1001 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
1002 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1003 "       f  = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
1004 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
1005 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
1006 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
1007 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1008 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1009 "       gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
1010 "}\n"
1011 "#endif\n"
1012 "#else // !MODE_WATER\n"
1013 "\n"
1014 "\n"
1015 "\n"
1016 "\n"
1017 "// common definitions between vertex shader and fragment shader:\n"
1018 "\n"
1019 "varying mediump vec2 TexCoord;\n"
1020 "#ifdef USEVERTEXTEXTUREBLEND\n"
1021 "varying mediump vec2 TexCoord2;\n"
1022 "#endif\n"
1023 "#ifdef USELIGHTMAP\n"
1024 "varying mediump vec2 TexCoordLightmap;\n"
1025 "#endif\n"
1026 "\n"
1027 "#ifdef MODE_LIGHTSOURCE\n"
1028 "varying mediump vec3 CubeVector;\n"
1029 "#endif\n"
1030 "\n"
1031 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1032 "varying mediump vec3 LightVector;\n"
1033 "#endif\n"
1034 "\n"
1035 "#ifdef USEEYEVECTOR\n"
1036 "varying highp vec3 EyeVector;\n"
1037 "#endif\n"
1038 "#ifdef USEFOG\n"
1039 "varying highp vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1040 "#endif\n"
1041 "\n"
1042 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1043 "varying lowp vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1044 "varying lowp vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1045 "varying lowp vec3 VectorR; // direction of R texcoord (surface normal)\n"
1046 "#endif\n"
1047 "\n"
1048 "#ifdef USEREFLECTION\n"
1049 "varying highp vec4 ModelViewProjectionPosition;\n"
1050 "#endif\n"
1051 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1052 "uniform highp vec3 LightPosition;\n"
1053 "varying highp vec4 ModelViewPosition;\n"
1054 "#endif\n"
1055 "\n"
1056 "#ifdef MODE_LIGHTSOURCE\n"
1057 "uniform highp vec3 LightPosition;\n"
1058 "#endif\n"
1059 "uniform highp vec3 EyePosition;\n"
1060 "#ifdef MODE_LIGHTDIRECTION\n"
1061 "uniform highp vec3 LightDir;\n"
1062 "#endif\n"
1063 "uniform highp vec4 FogPlane;\n"
1064 "\n"
1065 "#ifdef USESHADOWMAPORTHO\n"
1066 "varying mediump vec3 ShadowMapTC;\n"
1067 "#endif\n"
1068 "\n"
1069 "\n"
1070 "\n"
1071 "\n"
1072 "\n"
1073 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
1074 "\n"
1075 "// fragment shader specific:\n"
1076 "#ifdef FRAGMENT_SHADER\n"
1077 "\n"
1078 "uniform sampler2D Texture_Normal;\n"
1079 "uniform sampler2D Texture_Color;\n"
1080 "uniform sampler2D Texture_Gloss;\n"
1081 "#ifdef USEGLOW\n"
1082 "uniform sampler2D Texture_Glow;\n"
1083 "#endif\n"
1084 "#ifdef USEVERTEXTEXTUREBLEND\n"
1085 "uniform sampler2D Texture_SecondaryNormal;\n"
1086 "uniform sampler2D Texture_SecondaryColor;\n"
1087 "uniform sampler2D Texture_SecondaryGloss;\n"
1088 "#ifdef USEGLOW\n"
1089 "uniform sampler2D Texture_SecondaryGlow;\n"
1090 "#endif\n"
1091 "#endif\n"
1092 "#ifdef USECOLORMAPPING\n"
1093 "uniform sampler2D Texture_Pants;\n"
1094 "uniform sampler2D Texture_Shirt;\n"
1095 "#endif\n"
1096 "#ifdef USEFOG\n"
1097 "#ifdef USEFOGHEIGHTTEXTURE\n"
1098 "uniform sampler2D Texture_FogHeightTexture;\n"
1099 "#endif\n"
1100 "uniform sampler2D Texture_FogMask;\n"
1101 "#endif\n"
1102 "#ifdef USELIGHTMAP\n"
1103 "uniform sampler2D Texture_Lightmap;\n"
1104 "#endif\n"
1105 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1106 "uniform sampler2D Texture_Deluxemap;\n"
1107 "#endif\n"
1108 "#ifdef USEREFLECTION\n"
1109 "uniform sampler2D Texture_Reflection;\n"
1110 "#endif\n"
1111 "\n"
1112 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1113 "uniform sampler2D Texture_ScreenDepth;\n"
1114 "uniform sampler2D Texture_ScreenNormalMap;\n"
1115 "#endif\n"
1116 "#ifdef USEDEFERREDLIGHTMAP\n"
1117 "uniform sampler2D Texture_ScreenDiffuse;\n"
1118 "uniform sampler2D Texture_ScreenSpecular;\n"
1119 "#endif\n"
1120 "\n"
1121 "uniform lowp vec3 Color_Pants;\n"
1122 "uniform lowp vec3 Color_Shirt;\n"
1123 "uniform lowp vec3 FogColor;\n"
1124 "\n"
1125 "#ifdef USEFOG\n"
1126 "uniform highp float FogRangeRecip;\n"
1127 "uniform highp float FogPlaneViewDist;\n"
1128 "uniform highp float FogHeightFade;\n"
1129 "vec3 FogVertex(vec3 surfacecolor)\n"
1130 "{\n"
1131 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1132 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1133 "       float fogfrac;\n"
1134 "#ifdef USEFOGHEIGHTTEXTURE\n"
1135 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1136 "       fogfrac = fogheightpixel.a;\n"
1137 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1138 "#else\n"
1139 "# ifdef USEFOGOUTSIDE\n"
1140 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1141 "# else\n"
1142 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1143 "# endif\n"
1144 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1145 "#endif\n"
1146 "}\n"
1147 "#endif\n"
1148 "\n"
1149 "#ifdef USEOFFSETMAPPING\n"
1150 "uniform mediump float OffsetMapping_Scale;\n"
1151 "vec2 OffsetMapping(vec2 TexCoord)\n"
1152 "{\n"
1153 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1154 "       // 14 sample relief mapping: linear search and then binary search\n"
1155 "       // this basically steps forward a small amount repeatedly until it finds\n"
1156 "       // itself inside solid, then jitters forward and back using decreasing\n"
1157 "       // amounts to find the impact\n"
1158 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1159 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1160 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1161 "       vec3 RT = vec3(TexCoord, 1);\n"
1162 "       OffsetVector *= 0.1;\n"
1163 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1164 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1165 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1166 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1167 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1168 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1169 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1170 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1171 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1172 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1173 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1174 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1175 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1176 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1177 "       return RT.xy;\n"
1178 "#else\n"
1179 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1180 "       // this basically moves forward the full distance, and then backs up based\n"
1181 "       // on height of samples\n"
1182 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1183 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1184 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1185 "       TexCoord += OffsetVector;\n"
1186 "       OffsetVector *= 0.5;\n"
1187 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1188 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1189 "       return TexCoord;\n"
1190 "#endif\n"
1191 "}\n"
1192 "#endif // USEOFFSETMAPPING\n"
1193 "\n"
1194 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1195 "uniform sampler2D Texture_Attenuation;\n"
1196 "uniform samplerCube Texture_Cube;\n"
1197 "#endif\n"
1198 "\n"
1199 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1200 "\n"
1201 "#ifdef USESHADOWMAP2D\n"
1202 "# ifdef USESHADOWSAMPLER\n"
1203 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1204 "# else\n"
1205 "uniform sampler2D Texture_ShadowMap2D;\n"
1206 "# endif\n"
1207 "#endif\n"
1208 "\n"
1209 "#ifdef USESHADOWMAPVSDCT\n"
1210 "uniform samplerCube Texture_CubeProjection;\n"
1211 "#endif\n"
1212 "\n"
1213 "#if defined(USESHADOWMAP2D)\n"
1214 "uniform mediump vec2 ShadowMap_TextureScale;\n"
1215 "uniform mediump vec4 ShadowMap_Parameters;\n"
1216 "#endif\n"
1217 "\n"
1218 "#if defined(USESHADOWMAP2D)\n"
1219 "# ifdef USESHADOWMAPORTHO\n"
1220 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1221 "# else\n"
1222 "#  ifdef USESHADOWMAPVSDCT\n"
1223 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1224 "{\n"
1225 "       vec3 adir = abs(dir);\n"
1226 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1227 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1228 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1229 "}\n"
1230 "#  else\n"
1231 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1232 "{\n"
1233 "       vec3 adir = abs(dir);\n"
1234 "       float ma = adir.z;\n"
1235 "       vec4 proj = vec4(dir, 2.5);\n"
1236 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1237 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1238 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1239 "       return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1240 "}\n"
1241 "#  endif\n"
1242 "# endif\n"
1243 "#endif // defined(USESHADOWMAP2D)\n"
1244 "\n"
1245 "# ifdef USESHADOWMAP2D\n"
1246 "float ShadowMapCompare(vec3 dir)\n"
1247 "{\n"
1248 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1249 "       float f;\n"
1250 "\n"
1251 "#  ifdef USESHADOWSAMPLER\n"
1252 "#    ifdef USESHADOWMAPPCF\n"
1253 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1254 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1255 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1256 "#    else\n"
1257 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1258 "#    endif\n"
1259 "#  else\n"
1260 "#    ifdef USESHADOWMAPPCF\n"
1261 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1262 "#      ifdef GL_ARB_texture_gather\n"
1263 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1264 "#      else\n"
1265 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1266 "#      endif\n"
1267 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1268 "#      if USESHADOWMAPPCF > 1\n"
1269 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1270 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1271 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1272 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1273 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1274 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1275 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1276 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1277 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1278 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1279 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1280 "       locols.yz += group2.ab;\n"
1281 "       hicols.yz += group8.rg;\n"
1282 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1283 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1284 "                               mix(locols, hicols, offset.y);\n"
1285 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1286 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1287 "       f = dot(cols, vec4(1.0/25.0));\n"
1288 "#      else\n"
1289 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1290 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1291 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1292 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1293 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1294 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1295 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1296 "#      endif\n"
1297 "#     else\n"
1298 "#      ifdef GL_EXT_gpu_shader4\n"
1299 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1300 "#      else\n"
1301 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1302 "#      endif\n"
1303 "#      if USESHADOWMAPPCF > 1\n"
1304 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1305 "       center *= ShadowMap_TextureScale;\n"
1306 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1307 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1308 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1309 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1310 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1311 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1312 "#      else\n"
1313 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1314 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1315 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1316 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1317 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1318 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1319 "#      endif\n"
1320 "#     endif\n"
1321 "#    else\n"
1322 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1323 "#    endif\n"
1324 "#  endif\n"
1325 "#  ifdef USESHADOWMAPORTHO\n"
1326 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1327 "#  else\n"
1328 "       return f;\n"
1329 "#  endif\n"
1330 "}\n"
1331 "# endif\n"
1332 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1333 "#endif // FRAGMENT_SHADER\n"
1334 "\n"
1335 "\n"
1336 "\n"
1337 "\n"
1338 "#ifdef MODE_DEFERREDGEOMETRY\n"
1339 "#ifdef VERTEX_SHADER\n"
1340 "uniform highp mat4 TexMatrix;\n"
1341 "#ifdef USEVERTEXTEXTUREBLEND\n"
1342 "uniform highp mat4 BackgroundTexMatrix;\n"
1343 "#endif\n"
1344 "uniform highp mat4 ModelViewMatrix;\n"
1345 "void main(void)\n"
1346 "{\n"
1347 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1348 "#ifdef USEVERTEXTEXTUREBLEND\n"
1349 "       VertexColor = Attrib_Color;\n"
1350 "       TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1351 "#endif\n"
1352 "\n"
1353 "       // transform unnormalized eye direction into tangent space\n"
1354 "#ifdef USEOFFSETMAPPING\n"
1355 "       vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1356 "       EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1357 "       EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1358 "       EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1359 "#endif\n"
1360 "\n"
1361 "       VectorS = (ModelViewMatrix * vec4(Attrib_TexCoord1.xyz, 0)).xyz;\n"
1362 "       VectorT = (ModelViewMatrix * vec4(Attrib_TexCoord2.xyz, 0)).xyz;\n"
1363 "       VectorR = (ModelViewMatrix * vec4(Attrib_TexCoord3.xyz, 0)).xyz;\n"
1364 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1365 "}\n"
1366 "#endif // VERTEX_SHADER\n"
1367 "\n"
1368 "#ifdef FRAGMENT_SHADER\n"
1369 "void main(void)\n"
1370 "{\n"
1371 "#ifdef USEOFFSETMAPPING\n"
1372 "       // apply offsetmapping\n"
1373 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1374 "#define TexCoord TexCoordOffset\n"
1375 "#endif\n"
1376 "\n"
1377 "#ifdef USEALPHAKILL\n"
1378 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1379 "               discard;\n"
1380 "#endif\n"
1381 "\n"
1382 "#ifdef USEVERTEXTEXTUREBLEND\n"
1383 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1384 "       float terrainblend = clamp(float(VertexColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1385 "       //float terrainblend = min(float(VertexColor.a) * alpha * 2.0, float(1.0));\n"
1386 "       //float terrainblend = float(VertexColor.a) * alpha > 0.5;\n"
1387 "#endif\n"
1388 "\n"
1389 "#ifdef USEVERTEXTEXTUREBLEND\n"
1390 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1391 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1392 "#else\n"
1393 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1394 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1395 "#endif\n"
1396 "\n"
1397 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1398 "}\n"
1399 "#endif // FRAGMENT_SHADER\n"
1400 "#else // !MODE_DEFERREDGEOMETRY\n"
1401 "\n"
1402 "\n"
1403 "\n"
1404 "\n"
1405 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1406 "#ifdef VERTEX_SHADER\n"
1407 "uniform highp mat4 ModelViewMatrix;\n"
1408 "void main(void)\n"
1409 "{\n"
1410 "       ModelViewPosition = ModelViewMatrix * Attrib_Position;\n"
1411 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1412 "}\n"
1413 "#endif // VERTEX_SHADER\n"
1414 "\n"
1415 "#ifdef FRAGMENT_SHADER\n"
1416 "uniform highp mat4 ViewToLight;\n"
1417 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1418 "uniform highp vec2 ScreenToDepth;\n"
1419 "uniform myhalf3 DeferredColor_Ambient;\n"
1420 "uniform myhalf3 DeferredColor_Diffuse;\n"
1421 "#ifdef USESPECULAR\n"
1422 "uniform myhalf3 DeferredColor_Specular;\n"
1423 "uniform myhalf SpecularPower;\n"
1424 "#endif\n"
1425 "uniform myhalf2 PixelToScreenTexCoord;\n"
1426 "void main(void)\n"
1427 "{\n"
1428 "       // calculate viewspace pixel position\n"
1429 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1430 "       vec3 position;\n"
1431 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1432 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1433 "       // decode viewspace pixel normal\n"
1434 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1435 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1436 "       // surfacenormal = pixel normal in viewspace\n"
1437 "       // LightVector = pixel to light in viewspace\n"
1438 "       // CubeVector = position in lightspace\n"
1439 "       // eyevector = pixel to view in viewspace\n"
1440 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1441 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1442 "#ifdef USEDIFFUSE\n"
1443 "       // calculate diffuse shading\n"
1444 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1445 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1446 "#endif\n"
1447 "#ifdef USESPECULAR\n"
1448 "       // calculate directional shading\n"
1449 "       vec3 eyevector = position * -1.0;\n"
1450 "#  ifdef USEEXACTSPECULARMATH\n"
1451 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1452 "#  else\n"
1453 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1454 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1455 "#  endif\n"
1456 "#endif\n"
1457 "\n"
1458 "#if defined(USESHADOWMAP2D)\n"
1459 "       fade *= ShadowMapCompare(CubeVector);\n"
1460 "#endif\n"
1461 "\n"
1462 "#ifdef USEDIFFUSE\n"
1463 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1464 "#else\n"
1465 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1466 "#endif\n"
1467 "#ifdef USESPECULAR\n"
1468 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1469 "#else\n"
1470 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1471 "#endif\n"
1472 "\n"
1473 "# ifdef USECUBEFILTER\n"
1474 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1475 "       gl_FragData[0].rgb *= cubecolor;\n"
1476 "       gl_FragData[1].rgb *= cubecolor;\n"
1477 "# endif\n"
1478 "}\n"
1479 "#endif // FRAGMENT_SHADER\n"
1480 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1481 "\n"
1482 "\n"
1483 "\n"
1484 "\n"
1485 "#ifdef VERTEX_SHADER\n"
1486 "uniform highp mat4 TexMatrix;\n"
1487 "#ifdef USEVERTEXTEXTUREBLEND\n"
1488 "uniform highp mat4 BackgroundTexMatrix;\n"
1489 "#endif\n"
1490 "#ifdef MODE_LIGHTSOURCE\n"
1491 "uniform highp mat4 ModelToLight;\n"
1492 "#endif\n"
1493 "#ifdef USESHADOWMAPORTHO\n"
1494 "uniform highp mat4 ShadowMapMatrix;\n"
1495 "#endif\n"
1496 "void main(void)\n"
1497 "{\n"
1498 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1499 "       VertexColor = Attrib_Color;\n"
1500 "#endif\n"
1501 "       // copy the surface texcoord\n"
1502 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1503 "#ifdef USEVERTEXTEXTUREBLEND\n"
1504 "       TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1505 "#endif\n"
1506 "#ifdef USELIGHTMAP\n"
1507 "       TexCoordLightmap = vec2(Attrib_TexCoord4);\n"
1508 "#endif\n"
1509 "\n"
1510 "#ifdef MODE_LIGHTSOURCE\n"
1511 "       // transform vertex position into light attenuation/cubemap space\n"
1512 "       // (-1 to +1 across the light box)\n"
1513 "       CubeVector = vec3(ModelToLight * Attrib_Position);\n"
1514 "\n"
1515 "# ifdef USEDIFFUSE\n"
1516 "       // transform unnormalized light direction into tangent space\n"
1517 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1518 "       //  normalize it per pixel)\n"
1519 "       vec3 lightminusvertex = LightPosition - Attrib_Position.xyz;\n"
1520 "       LightVector.x = dot(lightminusvertex, Attrib_TexCoord1.xyz);\n"
1521 "       LightVector.y = dot(lightminusvertex, Attrib_TexCoord2.xyz);\n"
1522 "       LightVector.z = dot(lightminusvertex, Attrib_TexCoord3.xyz);\n"
1523 "# endif\n"
1524 "#endif\n"
1525 "\n"
1526 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1527 "       LightVector.x = dot(LightDir, Attrib_TexCoord1.xyz);\n"
1528 "       LightVector.y = dot(LightDir, Attrib_TexCoord2.xyz);\n"
1529 "       LightVector.z = dot(LightDir, Attrib_TexCoord3.xyz);\n"
1530 "#endif\n"
1531 "\n"
1532 "       // transform unnormalized eye direction into tangent space\n"
1533 "#ifdef USEEYEVECTOR\n"
1534 "       vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1535 "       EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1536 "       EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1537 "       EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1538 "#endif\n"
1539 "\n"
1540 "#ifdef USEFOG\n"
1541 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - Attrib_Position.xyz;\n"
1542 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, Attrib_Position);\n"
1543 "#endif\n"
1544 "\n"
1545 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1546 "       VectorS = Attrib_TexCoord1.xyz;\n"
1547 "       VectorT = Attrib_TexCoord2.xyz;\n"
1548 "       VectorR = Attrib_TexCoord3.xyz;\n"
1549 "#endif\n"
1550 "\n"
1551 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1552 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1553 "\n"
1554 "#ifdef USESHADOWMAPORTHO\n"
1555 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1556 "#endif\n"
1557 "\n"
1558 "#ifdef USEREFLECTION\n"
1559 "       ModelViewProjectionPosition = gl_Position;\n"
1560 "#endif\n"
1561 "}\n"
1562 "#endif // VERTEX_SHADER\n"
1563 "\n"
1564 "\n"
1565 "\n"
1566 "\n"
1567 "#ifdef FRAGMENT_SHADER\n"
1568 "#ifdef USEDEFERREDLIGHTMAP\n"
1569 "uniform myhalf2 PixelToScreenTexCoord;\n"
1570 "uniform myhalf3 DeferredMod_Diffuse;\n"
1571 "uniform myhalf3 DeferredMod_Specular;\n"
1572 "#endif\n"
1573 "uniform myhalf3 Color_Ambient;\n"
1574 "uniform myhalf3 Color_Diffuse;\n"
1575 "uniform myhalf3 Color_Specular;\n"
1576 "uniform myhalf SpecularPower;\n"
1577 "#ifdef USEGLOW\n"
1578 "uniform myhalf3 Color_Glow;\n"
1579 "#endif\n"
1580 "uniform myhalf Alpha;\n"
1581 "#ifdef USEREFLECTION\n"
1582 "uniform mediump vec4 DistortScaleRefractReflect;\n"
1583 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
1584 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
1585 "uniform lowp vec4 ReflectColor;\n"
1586 "#endif\n"
1587 "#ifdef USEREFLECTCUBE\n"
1588 "uniform highp mat4 ModelToReflectCube;\n"
1589 "uniform sampler2D Texture_ReflectMask;\n"
1590 "uniform samplerCube Texture_ReflectCube;\n"
1591 "#endif\n"
1592 "#ifdef MODE_LIGHTDIRECTION\n"
1593 "uniform myhalf3 LightColor;\n"
1594 "#endif\n"
1595 "#ifdef MODE_LIGHTSOURCE\n"
1596 "uniform myhalf3 LightColor;\n"
1597 "#endif\n"
1598 "void main(void)\n"
1599 "{\n"
1600 "#ifdef USEOFFSETMAPPING\n"
1601 "       // apply offsetmapping\n"
1602 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1603 "#define TexCoord TexCoordOffset\n"
1604 "#endif\n"
1605 "\n"
1606 "       // combine the diffuse textures (base, pants, shirt)\n"
1607 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1608 "#ifdef USEALPHAKILL\n"
1609 "       if (color.a < 0.5)\n"
1610 "               discard;\n"
1611 "#endif\n"
1612 "       color.a *= Alpha;\n"
1613 "#ifdef USECOLORMAPPING\n"
1614 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1615 "#endif\n"
1616 "#ifdef USEVERTEXTEXTUREBLEND\n"
1617 "       myhalf terrainblend = clamp(myhalf(VertexColor.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1618 "       //myhalf terrainblend = min(myhalf(VertexColor.a) * color.a * 2.0, myhalf(1.0));\n"
1619 "       //myhalf terrainblend = myhalf(VertexColor.a) * color.a > 0.5;\n"
1620 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1621 "       color.a = 1.0;\n"
1622 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1623 "#endif\n"
1624 "\n"
1625 "       // get the surface normal\n"
1626 "#ifdef USEVERTEXTEXTUREBLEND\n"
1627 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1628 "#else\n"
1629 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1630 "#endif\n"
1631 "\n"
1632 "       // get the material colors\n"
1633 "       myhalf3 diffusetex = color.rgb;\n"
1634 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1635 "# ifdef USEVERTEXTEXTUREBLEND\n"
1636 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1637 "# else\n"
1638 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1639 "# endif\n"
1640 "#endif\n"
1641 "\n"
1642 "#ifdef USEREFLECTCUBE\n"
1643 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1644 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1645 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1646 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1647 "#endif\n"
1648 "\n"
1649 "\n"
1650 "\n"
1651 "\n"
1652 "#ifdef MODE_LIGHTSOURCE\n"
1653 "       // light source\n"
1654 "#ifdef USEDIFFUSE\n"
1655 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1656 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1657 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1658 "#ifdef USESPECULAR\n"
1659 "#ifdef USEEXACTSPECULARMATH\n"
1660 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1661 "#else\n"
1662 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1663 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1664 "#endif\n"
1665 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1666 "#endif\n"
1667 "#else\n"
1668 "       color.rgb = diffusetex * Color_Ambient;\n"
1669 "#endif\n"
1670 "       color.rgb *= LightColor;\n"
1671 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1672 "#if defined(USESHADOWMAP2D)\n"
1673 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1674 "#endif\n"
1675 "# ifdef USECUBEFILTER\n"
1676 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1677 "# endif\n"
1678 "#endif // MODE_LIGHTSOURCE\n"
1679 "\n"
1680 "\n"
1681 "\n"
1682 "\n"
1683 "#ifdef MODE_LIGHTDIRECTION\n"
1684 "#define SHADING\n"
1685 "#ifdef USEDIFFUSE\n"
1686 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1687 "#endif\n"
1688 "#define lightcolor LightColor\n"
1689 "#endif // MODE_LIGHTDIRECTION\n"
1690 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1691 "#define SHADING\n"
1692 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1693 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1694 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1695 "       // convert modelspace light vector to tangentspace\n"
1696 "       myhalf3 lightnormal;\n"
1697 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1698 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1699 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1700 "       lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1701 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1702 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1703 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1704 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1705 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1706 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1707 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1708 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1709 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1710 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1711 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1712 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1713 "#define SHADING\n"
1714 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1715 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1716 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1717 "#endif\n"
1718 "\n"
1719 "\n"
1720 "\n"
1721 "\n"
1722 "#ifdef MODE_FAKELIGHT\n"
1723 "#define SHADING\n"
1724 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1725 "myhalf3 lightcolor = myhalf3(1.0);\n"
1726 "#endif // MODE_FAKELIGHT\n"
1727 "\n"
1728 "\n"
1729 "\n"
1730 "\n"
1731 "#ifdef MODE_LIGHTMAP\n"
1732 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1733 "#endif // MODE_LIGHTMAP\n"
1734 "#ifdef MODE_VERTEXCOLOR\n"
1735 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(VertexColor.rgb) * Color_Diffuse);\n"
1736 "#endif // MODE_VERTEXCOLOR\n"
1737 "#ifdef MODE_FLATCOLOR\n"
1738 "       color.rgb = diffusetex * Color_Ambient;\n"
1739 "#endif // MODE_FLATCOLOR\n"
1740 "\n"
1741 "\n"
1742 "\n"
1743 "\n"
1744 "#ifdef SHADING\n"
1745 "# ifdef USEDIFFUSE\n"
1746 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1747 "#  ifdef USESPECULAR\n"
1748 "#   ifdef USEEXACTSPECULARMATH\n"
1749 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1750 "#   else\n"
1751 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1752 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1753 "#   endif\n"
1754 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1755 "#  else\n"
1756 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1757 "#  endif\n"
1758 "# else\n"
1759 "       color.rgb = diffusetex * Color_Ambient;\n"
1760 "# endif\n"
1761 "#endif\n"
1762 "\n"
1763 "#ifdef USESHADOWMAPORTHO\n"
1764 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1765 "#endif\n"
1766 "\n"
1767 "#ifdef USEDEFERREDLIGHTMAP\n"
1768 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1769 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1770 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1771 "#endif\n"
1772 "\n"
1773 "#ifdef USEGLOW\n"
1774 "#ifdef USEVERTEXTEXTUREBLEND\n"
1775 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1776 "#else\n"
1777 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1778 "#endif\n"
1779 "#endif\n"
1780 "\n"
1781 "#ifdef USEFOG\n"
1782 "       color.rgb = FogVertex(color.rgb);\n"
1783 "#endif\n"
1784 "\n"
1785 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1786 "#ifdef USEREFLECTION\n"
1787 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1788 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1789 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1790 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1791 "       // FIXME temporary hack to detect the case that the reflection\n"
1792 "       // gets blackened at edges due to leaving the area that contains actual\n"
1793 "       // content.\n"
1794 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1795 "       // 'appening.\n"
1796 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1797 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1798 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1799 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1800 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1801 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1802 "#endif\n"
1803 "\n"
1804 "       gl_FragColor = vec4(color);\n"
1805 "}\n"
1806 "#endif // FRAGMENT_SHADER\n"
1807 "\n"
1808 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1809 "#endif // !MODE_DEFERREDGEOMETRY\n"
1810 "#endif // !MODE_WATER\n"
1811 "#endif // !MODE_REFRACTION\n"
1812 "#endif // !MODE_BLOOMBLUR\n"
1813 "#endif // !MODE_GENERIC\n"
1814 "#endif // !MODE_POSTPROCESS\n"
1815 "#endif // !MODE_SHOWDEPTH\n"
1816 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1817 ;
1818
1819 /*
1820 =========================================================================================================================================================
1821
1822
1823
1824 =========================================================================================================================================================
1825
1826
1827
1828 =========================================================================================================================================================
1829
1830
1831
1832 =========================================================================================================================================================
1833
1834
1835
1836 =========================================================================================================================================================
1837
1838
1839
1840 =========================================================================================================================================================
1841
1842
1843
1844 =========================================================================================================================================================
1845 */
1846
1847 const char *builtinhlslshaderstring =
1848 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1849 "// written by Forest 'LordHavoc' Hale\n"
1850 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1851 "\n"
1852 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1853 "#if defined(USEREFLECTION)\n"
1854 "#undef USESHADOWMAPORTHO\n"
1855 "#endif\n"
1856 "\n"
1857 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1858 "# define USEFOG\n"
1859 "#endif\n"
1860 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1861 "#define USELIGHTMAP\n"
1862 "#endif\n"
1863 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1864 "#define USEEYEVECTOR\n"
1865 "#endif\n"
1866 "\n"
1867 "#ifdef FRAGMENT_SHADER\n"
1868 "#ifdef HLSL\n"
1869 "//#undef USESHADOWMAPPCF\n"
1870 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1871 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1872 "#else\n"
1873 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1874 "#endif\n"
1875 "#endif\n"
1876 "\n"
1877 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1878 "#ifdef VERTEX_SHADER\n"
1879 "void main\n"
1880 "(\n"
1881 "float4 gl_Vertex : POSITION,\n"
1882 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1883 "out float4 gl_Position : POSITION,\n"
1884 "out float Depth : TEXCOORD0\n"
1885 ")\n"
1886 "{\n"
1887 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1888 "       Depth = gl_Position.z;\n"
1889 "}\n"
1890 "#endif\n"
1891 "\n"
1892 "#ifdef FRAGMENT_SHADER\n"
1893 "void main\n"
1894 "(\n"
1895 "float Depth : TEXCOORD0,\n"
1896 "out float4 gl_FragColor : COLOR\n"
1897 ")\n"
1898 "{\n"
1899 "//     float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1900 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1901 "       temp.yz -= floor(temp.yz);\n"
1902 "       gl_FragColor = temp;\n"
1903 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1904 "}\n"
1905 "#endif\n"
1906 "#else // !MODE_DEPTH_ORSHADOW\n"
1907 "\n"
1908 "\n"
1909 "\n"
1910 "\n"
1911 "#ifdef MODE_SHOWDEPTH\n"
1912 "#ifdef VERTEX_SHADER\n"
1913 "void main\n"
1914 "(\n"
1915 "float4 gl_Vertex : POSITION,\n"
1916 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1917 "out float4 gl_Position : POSITION,\n"
1918 "out float4 gl_FrontColor : COLOR0\n"
1919 ")\n"
1920 "{\n"
1921 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1922 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1923 "}\n"
1924 "#endif\n"
1925 "\n"
1926 "#ifdef FRAGMENT_SHADER\n"
1927 "void main\n"
1928 "(\n"
1929 "float4 gl_FrontColor : COLOR0,\n"
1930 "out float4 gl_FragColor : COLOR\n"
1931 ")\n"
1932 "{\n"
1933 "       gl_FragColor = gl_FrontColor;\n"
1934 "}\n"
1935 "#endif\n"
1936 "#else // !MODE_SHOWDEPTH\n"
1937 "\n"
1938 "\n"
1939 "\n"
1940 "\n"
1941 "#ifdef MODE_POSTPROCESS\n"
1942 "\n"
1943 "#ifdef VERTEX_SHADER\n"
1944 "void main\n"
1945 "(\n"
1946 "float4 gl_Vertex : POSITION,\n"
1947 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1948 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1949 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1950 "out float4 gl_Position : POSITION,\n"
1951 "out float2 TexCoord1 : TEXCOORD0,\n"
1952 "out float2 TexCoord2 : TEXCOORD1\n"
1953 ")\n"
1954 "{\n"
1955 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1956 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1957 "#ifdef USEBLOOM\n"
1958 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1959 "#endif\n"
1960 "}\n"
1961 "#endif\n"
1962 "\n"
1963 "#ifdef FRAGMENT_SHADER\n"
1964 "void main\n"
1965 "(\n"
1966 "float2 TexCoord1 : TEXCOORD0,\n"
1967 "float2 TexCoord2 : TEXCOORD1,\n"
1968 "uniform sampler Texture_First : register(s0),\n"
1969 "#ifdef USEBLOOM\n"
1970 "uniform sampler Texture_Second : register(s1),\n"
1971 "#endif\n"
1972 "#ifdef USEGAMMARAMPS\n"
1973 "uniform sampler Texture_GammaRamps : register(s2),\n"
1974 "#endif\n"
1975 "#ifdef USESATURATION\n"
1976 "uniform float Saturation : register(c30),\n"
1977 "#endif\n"
1978 "#ifdef USEVIEWTINT\n"
1979 "uniform float4 ViewTintColor : register(c41),\n"
1980 "#endif\n"
1981 "uniform float4 UserVec1 : register(c37),\n"
1982 "uniform float4 UserVec2 : register(c38),\n"
1983 "uniform float4 UserVec3 : register(c39),\n"
1984 "uniform float4 UserVec4 : register(c40),\n"
1985 "uniform float ClientTime : register(c2),\n"
1986 "uniform float2 PixelSize : register(c25),\n"
1987 "uniform float4 BloomColorSubtract : register(c43),\n"
1988 "out float4 gl_FragColor : COLOR\n"
1989 ")\n"
1990 "{\n"
1991 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1992 "#ifdef USEBLOOM\n"
1993 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1994 "#endif\n"
1995 "#ifdef USEVIEWTINT\n"
1996 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1997 "#endif\n"
1998 "\n"
1999 "#ifdef USEPOSTPROCESSING\n"
2000 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
2001 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
2002 "       float sobel = 1.0;\n"
2003 "       // float2 ts = textureSize(Texture_First, 0);\n"
2004 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
2005 "       float2 px = PixelSize;\n"
2006 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2007 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
2008 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2009 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2010 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
2011 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2012 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2013 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
2014 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2015 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2016 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
2017 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2018 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2019 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2020 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2021 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2022 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2023 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2024 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2025 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2026 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2027 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2028 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2029 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2030 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2031 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2032 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2033 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2034 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2035 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2036 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2037 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2038 "#endif\n"
2039 "\n"
2040 "#ifdef USESATURATION\n"
2041 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2042 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2043 "       // 'vampire sight' effect, wheres red is compensated\n"
2044 "       #ifdef SATURATION_REDCOMPENSATE\n"
2045 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2046 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2047 "               gl_FragColor.r += r;\n"
2048 "       #else\n"
2049 "               // normal desaturation\n"
2050 "               //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2051 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2052 "       #endif\n"
2053 "#endif\n"
2054 "\n"
2055 "#ifdef USEGAMMARAMPS\n"
2056 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2057 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2058 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2059 "#endif\n"
2060 "}\n"
2061 "#endif\n"
2062 "#else // !MODE_POSTPROCESS\n"
2063 "\n"
2064 "\n"
2065 "\n"
2066 "\n"
2067 "#ifdef MODE_GENERIC\n"
2068 "#ifdef VERTEX_SHADER\n"
2069 "void main\n"
2070 "(\n"
2071 "float4 gl_Vertex : POSITION,\n"
2072 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2073 "float4 gl_Color : COLOR0,\n"
2074 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2075 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2076 "out float4 gl_Position : POSITION,\n"
2077 "#ifdef USEDIFFUSE\n"
2078 "out float2 TexCoord1 : TEXCOORD0,\n"
2079 "#endif\n"
2080 "#ifdef USESPECULAR\n"
2081 "out float2 TexCoord2 : TEXCOORD1,\n"
2082 "#endif\n"
2083 "out float4 gl_FrontColor : COLOR\n"
2084 ")\n"
2085 "{\n"
2086 "#ifdef HLSL\n"
2087 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2088 "#else\n"
2089 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2090 "#endif\n"
2091 "#ifdef USEDIFFUSE\n"
2092 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2093 "#endif\n"
2094 "#ifdef USESPECULAR\n"
2095 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2096 "#endif\n"
2097 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2098 "}\n"
2099 "#endif\n"
2100 "\n"
2101 "#ifdef FRAGMENT_SHADER\n"
2102 "\n"
2103 "void main\n"
2104 "(\n"
2105 "float4 gl_FrontColor : COLOR0,\n"
2106 "float2 TexCoord1 : TEXCOORD0,\n"
2107 "float2 TexCoord2 : TEXCOORD1,\n"
2108 "#ifdef USEDIFFUSE\n"
2109 "uniform sampler Texture_First : register(s0),\n"
2110 "#endif\n"
2111 "#ifdef USESPECULAR\n"
2112 "uniform sampler Texture_Second : register(s1),\n"
2113 "#endif\n"
2114 "out float4 gl_FragColor : COLOR\n"
2115 ")\n"
2116 "{\n"
2117 "#ifdef USEVIEWTINT\n"
2118 "       gl_FragColor = gl_FrontColor;\n"
2119 "#else\n"
2120 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2121 "#endif\n"
2122 "#ifdef USEDIFFUSE\n"
2123 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2124 "#endif\n"
2125 "\n"
2126 "#ifdef USESPECULAR\n"
2127 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2128 "# ifdef USECOLORMAPPING\n"
2129 "       gl_FragColor *= tex2;\n"
2130 "# endif\n"
2131 "# ifdef USEGLOW\n"
2132 "       gl_FragColor += tex2;\n"
2133 "# endif\n"
2134 "# ifdef USEVERTEXTEXTUREBLEND\n"
2135 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2136 "# endif\n"
2137 "#endif\n"
2138 "}\n"
2139 "#endif\n"
2140 "#else // !MODE_GENERIC\n"
2141 "\n"
2142 "\n"
2143 "\n"
2144 "\n"
2145 "#ifdef MODE_BLOOMBLUR\n"
2146 "#ifdef VERTEX_SHADER\n"
2147 "void main\n"
2148 "(\n"
2149 "float4 gl_Vertex : POSITION,\n"
2150 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2151 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2152 "out float4 gl_Position : POSITION,\n"
2153 "out float2 TexCoord : TEXCOORD0\n"
2154 ")\n"
2155 "{\n"
2156 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2157 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2158 "}\n"
2159 "#endif\n"
2160 "\n"
2161 "#ifdef FRAGMENT_SHADER\n"
2162 "\n"
2163 "void main\n"
2164 "(\n"
2165 "float2 TexCoord : TEXCOORD0,\n"
2166 "uniform sampler Texture_First : register(s0),\n"
2167 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2168 "out float4 gl_FragColor : COLOR\n"
2169 ")\n"
2170 "{\n"
2171 "       int i;\n"
2172 "       float2 tc = TexCoord;\n"
2173 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2174 "       tc += BloomBlur_Parameters.xy;\n"
2175 "       for (i = 1;i < SAMPLES;i++)\n"
2176 "       {\n"
2177 "               color += tex2D(Texture_First, tc).rgb;\n"
2178 "               tc += BloomBlur_Parameters.xy;\n"
2179 "       }\n"
2180 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2181 "}\n"
2182 "#endif\n"
2183 "#else // !MODE_BLOOMBLUR\n"
2184 "#ifdef MODE_REFRACTION\n"
2185 "#ifdef VERTEX_SHADER\n"
2186 "void main\n"
2187 "(\n"
2188 "float4 gl_Vertex : POSITION,\n"
2189 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2190 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2191 "uniform float4x4 TexMatrix : register(c0),\n"
2192 "uniform float3 EyePosition : register(c24),\n"
2193 "out float4 gl_Position : POSITION,\n"
2194 "out float2 TexCoord : TEXCOORD0,\n"
2195 "out float3 EyeVector : TEXCOORD1,\n"
2196 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2197 ")\n"
2198 "{\n"
2199 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2200 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2201 "       ModelViewProjectionPosition = gl_Position;\n"
2202 "}\n"
2203 "#endif\n"
2204 "\n"
2205 "#ifdef FRAGMENT_SHADER\n"
2206 "void main\n"
2207 "(\n"
2208 "float2 TexCoord : TEXCOORD0,\n"
2209 "float3 EyeVector : TEXCOORD1,\n"
2210 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2211 "uniform sampler Texture_Normal : register(s0),\n"
2212 "uniform sampler Texture_Refraction : register(s3),\n"
2213 "uniform sampler Texture_Reflection : register(s7),\n"
2214 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2215 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2216 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2217 "uniform float4 RefractColor : register(c29),\n"
2218 "out float4 gl_FragColor : COLOR\n"
2219 ")\n"
2220 "{\n"
2221 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2222 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2223 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2224 "       float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2225 "       // FIXME temporary hack to detect the case that the reflection\n"
2226 "       // gets blackened at edges due to leaving the area that contains actual\n"
2227 "       // content.\n"
2228 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2229 "       // 'appening.\n"
2230 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2231 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2232 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2233 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2234 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2235 "       gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2236 "}\n"
2237 "#endif\n"
2238 "#else // !MODE_REFRACTION\n"
2239 "\n"
2240 "\n"
2241 "\n"
2242 "\n"
2243 "#ifdef MODE_WATER\n"
2244 "#ifdef VERTEX_SHADER\n"
2245 "\n"
2246 "void main\n"
2247 "(\n"
2248 "float4 gl_Vertex : POSITION,\n"
2249 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2250 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2251 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2252 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2253 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2254 "uniform float4x4 TexMatrix : register(c0),\n"
2255 "uniform float3 EyePosition : register(c24),\n"
2256 "out float4 gl_Position : POSITION,\n"
2257 "out float2 TexCoord : TEXCOORD0,\n"
2258 "out float3 EyeVector : TEXCOORD1,\n"
2259 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2260 ")\n"
2261 "{\n"
2262 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2263 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2264 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2265 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2266 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2267 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2268 "       ModelViewProjectionPosition = gl_Position;\n"
2269 "}\n"
2270 "#endif\n"
2271 "\n"
2272 "#ifdef FRAGMENT_SHADER\n"
2273 "void main\n"
2274 "(\n"
2275 "float2 TexCoord : TEXCOORD0,\n"
2276 "float3 EyeVector : TEXCOORD1,\n"
2277 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2278 "uniform sampler Texture_Normal : register(s0),\n"
2279 "uniform sampler Texture_Refraction : register(s3),\n"
2280 "uniform sampler Texture_Reflection : register(s7),\n"
2281 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2282 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2283 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2284 "uniform float4 RefractColor : register(c29),\n"
2285 "uniform float4 ReflectColor : register(c26),\n"
2286 "uniform float ReflectFactor : register(c27),\n"
2287 "uniform float ReflectOffset : register(c28),\n"
2288 "out float4 gl_FragColor : COLOR\n"
2289 ")\n"
2290 "{\n"
2291 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2292 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2293 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2294 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2295 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2296 "       // FIXME temporary hack to detect the case that the reflection\n"
2297 "       // gets blackened at edges due to leaving the area that contains actual\n"
2298 "       // content.\n"
2299 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2300 "       // 'appening.\n"
2301 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2302 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2303 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2304 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2305 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2306 "       f  = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2307 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2308 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2309 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2310 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2311 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2312 "       gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2313 "}\n"
2314 "#endif\n"
2315 "#else // !MODE_WATER\n"
2316 "\n"
2317 "\n"
2318 "\n"
2319 "\n"
2320 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
2321 "\n"
2322 "// fragment shader specific:\n"
2323 "#ifdef FRAGMENT_SHADER\n"
2324 "\n"
2325 "#ifdef USEFOG\n"
2326 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2327 "{\n"
2328 "       float fogfrac;\n"
2329 "#ifdef USEFOGHEIGHTTEXTURE\n"
2330 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2331 "       fogfrac = fogheightpixel.a;\n"
2332 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2333 "#else\n"
2334 "# ifdef USEFOGOUTSIDE\n"
2335 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2336 "# else\n"
2337 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2338 "# endif\n"
2339 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2340 "#endif\n"
2341 "}\n"
2342 "#endif\n"
2343 "\n"
2344 "#ifdef USEOFFSETMAPPING\n"
2345 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2346 "{\n"
2347 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2348 "       // 14 sample relief mapping: linear search and then binary search\n"
2349 "       // this basically steps forward a small amount repeatedly until it finds\n"
2350 "       // itself inside solid, then jitters forward and back using decreasing\n"
2351 "       // amounts to find the impact\n"
2352 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2353 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2354 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2355 "       float3 RT = float3(TexCoord, 1);\n"
2356 "       OffsetVector *= 0.1;\n"
2357 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2358 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2359 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2360 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2361 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2362 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2363 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2364 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2365 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2366 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2367 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2368 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2369 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2370 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2371 "       return RT.xy;\n"
2372 "#else\n"
2373 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2374 "       // this basically moves forward the full distance, and then backs up based\n"
2375 "       // on height of samples\n"
2376 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2377 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2378 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2379 "       TexCoord += OffsetVector;\n"
2380 "       OffsetVector *= 0.333;\n"
2381 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2382 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2383 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2384 "       return TexCoord;\n"
2385 "#endif\n"
2386 "}\n"
2387 "#endif // USEOFFSETMAPPING\n"
2388 "\n"
2389 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2390 "#if defined(USESHADOWMAP2D)\n"
2391 "# ifdef USESHADOWMAPORTHO\n"
2392 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2393 "# else\n"
2394 "#  ifdef USESHADOWMAPVSDCT\n"
2395 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2396 "{\n"
2397 "       float3 adir = abs(dir);\n"
2398 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2399 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2400 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2401 "}\n"
2402 "#  else\n"
2403 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2404 "{\n"
2405 "       float3 adir = abs(dir);\n"
2406 "       float ma = adir.z;\n"
2407 "       float4 proj = float4(dir, 2.5);\n"
2408 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2409 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2410 "#ifdef HLSL\n"
2411 "       return float3(proj.xy * ShadowMap_Parameters.x / ma + float2(0.5,0.5) + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, ma + 64 * ShadowMap_Parameters.w);\n"
2412 "#else\n"
2413 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2414 "       return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2415 "#endif\n"
2416 "}\n"
2417 "#  endif\n"
2418 "# endif\n"
2419 "#endif // defined(USESHADOWMAP2D)\n"
2420 "\n"
2421 "# ifdef USESHADOWMAP2D\n"
2422 "#ifdef USESHADOWMAPVSDCT\n"
2423 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2424 "#else\n"
2425 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2426 "#endif\n"
2427 "{\n"
2428 "#ifdef USESHADOWMAPVSDCT\n"
2429 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2430 "#else\n"
2431 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2432 "#endif\n"
2433 "       float f;\n"
2434 "\n"
2435 "#  ifdef USESHADOWSAMPLER\n"
2436 "#    ifdef USESHADOWMAPPCF\n"
2437 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2438 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2439 "       f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2440 "#    else\n"
2441 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2442 "#    endif\n"
2443 "#  else\n"
2444 "#    ifdef USESHADOWMAPPCF\n"
2445 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2446 "#      ifdef GL_ARB_texture_gather\n"
2447 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2448 "#      else\n"
2449 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2450 "#      endif\n"
2451 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2452 "#      if USESHADOWMAPPCF > 1\n"
2453 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2454 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2455 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2456 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2457 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2458 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2459 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2460 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2461 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2462 "       float4 locols = float4(group1.ab, group3.ab);\n"
2463 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2464 "       locols.yz += group2.ab;\n"
2465 "       hicols.yz += group8.rg;\n"
2466 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2467 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2468 "                               lerp(locols, hicols, offset.y);\n"
2469 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2470 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2471 "       f = dot(cols, float4(1.0/25.0));\n"
2472 "#      else\n"
2473 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2474 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2475 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2476 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2477 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2478 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2479 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2480 "#      endif\n"
2481 "#     else\n"
2482 "#      ifdef GL_EXT_gpu_shader4\n"
2483 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2484 "#      else\n"
2485 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2486 "#      endif\n"
2487 "#      if USESHADOWMAPPCF > 1\n"
2488 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2489 "       center *= ShadowMap_TextureScale;\n"
2490 "       float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2491 "       float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2492 "       float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2493 "       float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2494 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2495 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2496 "#      else\n"
2497 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2498 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2499 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2500 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2501 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2502 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2503 "#      endif\n"
2504 "#     endif\n"
2505 "#    else\n"
2506 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2507 "#    endif\n"
2508 "#  endif\n"
2509 "#  ifdef USESHADOWMAPORTHO\n"
2510 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2511 "#  else\n"
2512 "       return f;\n"
2513 "#  endif\n"
2514 "}\n"
2515 "# endif\n"
2516 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2517 "#endif // FRAGMENT_SHADER\n"
2518 "\n"
2519 "\n"
2520 "\n"
2521 "\n"
2522 "#ifdef MODE_DEFERREDGEOMETRY\n"
2523 "#ifdef VERTEX_SHADER\n"
2524 "void main\n"
2525 "(\n"
2526 "float4 gl_Vertex : POSITION,\n"
2527 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2528 "#ifdef USEVERTEXTEXTUREBLEND\n"
2529 "float4 gl_Color : COLOR0,\n"
2530 "#endif\n"
2531 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2532 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2533 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2534 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2535 "uniform float4x4 TexMatrix : register(c0),\n"
2536 "#ifdef USEVERTEXTEXTUREBLEND\n"
2537 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2538 "#endif\n"
2539 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2540 "#ifdef USEOFFSETMAPPING\n"
2541 "uniform float3 EyePosition : register(c24),\n"
2542 "#endif\n"
2543 "out float4 gl_Position : POSITION,\n"
2544 "#ifdef USEVERTEXTEXTUREBLEND\n"
2545 "out float4 gl_FrontColor : COLOR,\n"
2546 "#endif\n"
2547 "out float4 TexCoordBoth : TEXCOORD0,\n"
2548 "#ifdef USEOFFSETMAPPING\n"
2549 "out float3 EyeVector : TEXCOORD2,\n"
2550 "#endif\n"
2551 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2552 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2553 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2554 ")\n"
2555 "{\n"
2556 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2557 "#ifdef USEVERTEXTEXTUREBLEND\n"
2558 "#ifdef HLSL\n"
2559 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2560 "#else\n"
2561 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2562 "#endif\n"
2563 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2564 "#endif\n"
2565 "\n"
2566 "       // transform unnormalized eye direction into tangent space\n"
2567 "#ifdef USEOFFSETMAPPING\n"
2568 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2569 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2570 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2571 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2572 "#endif\n"
2573 "\n"
2574 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2575 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2576 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2577 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2578 "       VectorR.w = gl_Position.z;\n"
2579 "}\n"
2580 "#endif // VERTEX_SHADER\n"
2581 "\n"
2582 "#ifdef FRAGMENT_SHADER\n"
2583 "void main\n"
2584 "(\n"
2585 "float4 TexCoordBoth : TEXCOORD0,\n"
2586 "float3 EyeVector : TEXCOORD2,\n"
2587 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2588 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2589 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2590 "uniform sampler Texture_Normal : register(s0),\n"
2591 "#ifdef USEALPHAKILL\n"
2592 "uniform sampler Texture_Color : register(s1),\n"
2593 "#endif\n"
2594 "uniform sampler Texture_Gloss : register(s2),\n"
2595 "#ifdef USEVERTEXTEXTUREBLEND\n"
2596 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2597 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2598 "#endif\n"
2599 "#ifdef USEOFFSETMAPPING\n"
2600 "uniform float OffsetMapping_Scale : register(c24),\n"
2601 "#endif\n"
2602 "uniform half SpecularPower : register(c36),\n"
2603 "#ifdef HLSL\n"
2604 "out float4 gl_FragData0 : COLOR0,\n"
2605 "out float4 gl_FragData1 : COLOR1\n"
2606 "#else\n"
2607 "out float4 gl_FragColor : COLOR\n"
2608 "#endif\n"
2609 ")\n"
2610 "{\n"
2611 "       float2 TexCoord = TexCoordBoth.xy;\n"
2612 "#ifdef USEOFFSETMAPPING\n"
2613 "       // apply offsetmapping\n"
2614 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2615 "#define TexCoord TexCoordOffset\n"
2616 "#endif\n"
2617 "\n"
2618 "#ifdef USEALPHAKILL\n"
2619 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2620 "               discard;\n"
2621 "#endif\n"
2622 "\n"
2623 "#ifdef USEVERTEXTEXTUREBLEND\n"
2624 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2625 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2626 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2627 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2628 "#endif\n"
2629 "\n"
2630 "#ifdef USEVERTEXTEXTUREBLEND\n"
2631 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2632 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2633 "#else\n"
2634 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2635 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2636 "#endif\n"
2637 "\n"
2638 "#ifdef HLSL\n"
2639 "       gl_FragData0 = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR.xyz) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2640 "       float Depth = VectorR.w / 256.0;\n"
2641 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2642 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2643 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2644 "       gl_FragData1 = depthcolor;\n"
2645 "#else\n"
2646 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2647 "#endif\n"
2648 "}\n"
2649 "#endif // FRAGMENT_SHADER\n"
2650 "#else // !MODE_DEFERREDGEOMETRY\n"
2651 "\n"
2652 "\n"
2653 "\n"
2654 "\n"
2655 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2656 "#ifdef VERTEX_SHADER\n"
2657 "void main\n"
2658 "(\n"
2659 "float4 gl_Vertex : POSITION,\n"
2660 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2661 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2662 "out float4 gl_Position : POSITION,\n"
2663 "out float4 ModelViewPosition : TEXCOORD0\n"
2664 ")\n"
2665 "{\n"
2666 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2667 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2668 "}\n"
2669 "#endif // VERTEX_SHADER\n"
2670 "\n"
2671 "#ifdef FRAGMENT_SHADER\n"
2672 "void main\n"
2673 "(\n"
2674 "#ifdef HLSL\n"
2675 "float2 Pixel : VPOS,\n"
2676 "#else\n"
2677 "float2 Pixel : WPOS,\n"
2678 "#endif\n"
2679 "float4 ModelViewPosition : TEXCOORD0,\n"
2680 "uniform float4x4 ViewToLight : register(c44),\n"
2681 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2682 "uniform float3 LightPosition : register(c23),\n"
2683 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2684 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2685 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2686 "#ifdef USESPECULAR\n"
2687 "uniform half3 DeferredColor_Specular : register(c11),\n"
2688 "uniform half SpecularPower : register(c36),\n"
2689 "#endif\n"
2690 "uniform sampler Texture_Attenuation : register(s9),\n"
2691 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2692 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2693 "\n"
2694 "#ifdef USECUBEFILTER\n"
2695 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2696 "#endif\n"
2697 "\n"
2698 "#ifdef USESHADOWMAP2D\n"
2699 "# ifdef USESHADOWSAMPLER\n"
2700 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2701 "# else\n"
2702 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2703 "# endif\n"
2704 "#endif\n"
2705 "\n"
2706 "#ifdef USESHADOWMAPVSDCT\n"
2707 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2708 "#endif\n"
2709 "\n"
2710 "#if defined(USESHADOWMAP2D)\n"
2711 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2712 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2713 "#endif\n"
2714 "\n"
2715 "out float4 gl_FragData0 : COLOR0,\n"
2716 "out float4 gl_FragData1 : COLOR1\n"
2717 ")\n"
2718 "{\n"
2719 "       // calculate viewspace pixel position\n"
2720 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2721 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2722 "       float3 position;\n"
2723 "#ifdef HLSL\n"
2724 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2725 "#else\n"
2726 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2727 "#endif\n"
2728 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2729 "       // decode viewspace pixel normal\n"
2730 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2731 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2732 "       // surfacenormal = pixel normal in viewspace\n"
2733 "       // LightVector = pixel to light in viewspace\n"
2734 "       // CubeVector = position in lightspace\n"
2735 "       // eyevector = pixel to view in viewspace\n"
2736 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2737 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2738 "#ifdef USEDIFFUSE\n"
2739 "       // calculate diffuse shading\n"
2740 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2741 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2742 "#endif\n"
2743 "#ifdef USESPECULAR\n"
2744 "       // calculate directional shading\n"
2745 "       float3 eyevector = position * -1.0;\n"
2746 "#  ifdef USEEXACTSPECULARMATH\n"
2747 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2748 "#  else\n"
2749 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2750 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2751 "#  endif\n"
2752 "#endif\n"
2753 "\n"
2754 "#if defined(USESHADOWMAP2D)\n"
2755 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2756 "#ifdef USESHADOWMAPVSDCT\n"
2757 ", Texture_CubeProjection\n"
2758 "#endif\n"
2759 "       ));\n"
2760 "#endif\n"
2761 "\n"
2762 "#ifdef USEDIFFUSE\n"
2763 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2764 "#else\n"
2765 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2766 "#endif\n"
2767 "#ifdef USESPECULAR\n"
2768 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2769 "#else\n"
2770 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2771 "#endif\n"
2772 "\n"
2773 "# ifdef USECUBEFILTER\n"
2774 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2775 "       gl_FragData0.rgb *= cubecolor;\n"
2776 "       gl_FragData1.rgb *= cubecolor;\n"
2777 "# endif\n"
2778 "}\n"
2779 "#endif // FRAGMENT_SHADER\n"
2780 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2781 "\n"
2782 "\n"
2783 "\n"
2784 "\n"
2785 "#ifdef VERTEX_SHADER\n"
2786 "void main\n"
2787 "(\n"
2788 "float4 gl_Vertex : POSITION,\n"
2789 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2790 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2791 "float4 gl_Color : COLOR0,\n"
2792 "#endif\n"
2793 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2794 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2795 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2796 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2797 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2798 "\n"
2799 "uniform float3 EyePosition : register(c24),\n"
2800 "uniform float4x4 TexMatrix : register(c0),\n"
2801 "#ifdef USEVERTEXTEXTUREBLEND\n"
2802 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2803 "#endif\n"
2804 "#ifdef MODE_LIGHTSOURCE\n"
2805 "uniform float4x4 ModelToLight : register(c20),\n"
2806 "#endif\n"
2807 "#ifdef MODE_LIGHTSOURCE\n"
2808 "uniform float3 LightPosition : register(c27),\n"
2809 "#endif\n"
2810 "#ifdef MODE_LIGHTDIRECTION\n"
2811 "uniform float3 LightDir : register(c26),\n"
2812 "#endif\n"
2813 "uniform float4 FogPlane : register(c25),\n"
2814 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2815 "uniform float3 LightPosition : register(c27),\n"
2816 "#endif\n"
2817 "#ifdef USESHADOWMAPORTHO\n"
2818 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2819 "#endif\n"
2820 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2821 "out float4 gl_FrontColor : COLOR,\n"
2822 "#endif\n"
2823 "out float4 TexCoordBoth : TEXCOORD0,\n"
2824 "#ifdef USELIGHTMAP\n"
2825 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2826 "#endif\n"
2827 "#ifdef USEEYEVECTOR\n"
2828 "out float3 EyeVector : TEXCOORD2,\n"
2829 "#endif\n"
2830 "#ifdef USEREFLECTION\n"
2831 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2832 "#endif\n"
2833 "#ifdef USEFOG\n"
2834 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2835 "#endif\n"
2836 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2837 "out float3 LightVector : TEXCOORD1,\n"
2838 "#endif\n"
2839 "#ifdef MODE_LIGHTSOURCE\n"
2840 "out float3 CubeVector : TEXCOORD3,\n"
2841 "#endif\n"
2842 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2843 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2844 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2845 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2846 "#endif\n"
2847 "#ifdef USESHADOWMAPORTHO\n"
2848 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2849 "#endif\n"
2850 "out float4 gl_Position : POSITION\n"
2851 ")\n"
2852 "{\n"
2853 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2854 "#ifdef HLSL\n"
2855 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2856 "#else\n"
2857 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2858 "#endif\n"
2859 "#endif\n"
2860 "       // copy the surface texcoord\n"
2861 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2862 "#ifdef USEVERTEXTEXTUREBLEND\n"
2863 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2864 "#endif\n"
2865 "#ifdef USELIGHTMAP\n"
2866 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2867 "#endif\n"
2868 "\n"
2869 "#ifdef MODE_LIGHTSOURCE\n"
2870 "       // transform vertex position into light attenuation/cubemap space\n"
2871 "       // (-1 to +1 across the light box)\n"
2872 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2873 "\n"
2874 "# ifdef USEDIFFUSE\n"
2875 "       // transform unnormalized light direction into tangent space\n"
2876 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2877 "       //  normalize it per pixel)\n"
2878 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2879 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2880 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2881 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2882 "# endif\n"
2883 "#endif\n"
2884 "\n"
2885 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2886 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2887 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2888 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2889 "#endif\n"
2890 "\n"
2891 "       // transform unnormalized eye direction into tangent space\n"
2892 "#ifdef USEEYEVECTOR\n"
2893 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2894 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2895 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2896 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2897 "#endif\n"
2898 "\n"
2899 "#ifdef USEFOG\n"
2900 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2901 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2902 "#endif\n"
2903 "\n"
2904 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2905 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2906 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2907 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2908 "#endif\n"
2909 "\n"
2910 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2911 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2912 "\n"
2913 "#ifdef USESHADOWMAPORTHO\n"
2914 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2915 "#endif\n"
2916 "\n"
2917 "#ifdef USEREFLECTION\n"
2918 "       ModelViewProjectionPosition = gl_Position;\n"
2919 "#endif\n"
2920 "}\n"
2921 "#endif // VERTEX_SHADER\n"
2922 "\n"
2923 "\n"
2924 "\n"
2925 "\n"
2926 "#ifdef FRAGMENT_SHADER\n"
2927 "void main\n"
2928 "(\n"
2929 "#ifdef USEDEFERREDLIGHTMAP\n"
2930 "#ifdef HLSL\n"
2931 "float2 Pixel : VPOS,\n"
2932 "#else\n"
2933 "float2 Pixel : WPOS,\n"
2934 "#endif\n"
2935 "#endif\n"
2936 "float4 gl_FrontColor : COLOR,\n"
2937 "float4 TexCoordBoth : TEXCOORD0,\n"
2938 "#ifdef USELIGHTMAP\n"
2939 "float2 TexCoordLightmap : TEXCOORD1,\n"
2940 "#endif\n"
2941 "#ifdef USEEYEVECTOR\n"
2942 "float3 EyeVector : TEXCOORD2,\n"
2943 "#endif\n"
2944 "#ifdef USEREFLECTION\n"
2945 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2946 "#endif\n"
2947 "#ifdef USEFOG\n"
2948 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2949 "#endif\n"
2950 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2951 "float3 LightVector : TEXCOORD1,\n"
2952 "#endif\n"
2953 "#ifdef MODE_LIGHTSOURCE\n"
2954 "float3 CubeVector : TEXCOORD3,\n"
2955 "#endif\n"
2956 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2957 "float4 ModelViewPosition : TEXCOORD0,\n"
2958 "#endif\n"
2959 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2960 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2961 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2962 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2963 "#endif\n"
2964 "#ifdef USESHADOWMAPORTHO\n"
2965 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2966 "#endif\n"
2967 "\n"
2968 "uniform sampler Texture_Normal : register(s0),\n"
2969 "uniform sampler Texture_Color : register(s1),\n"
2970 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2971 "uniform sampler Texture_Gloss : register(s2),\n"
2972 "#endif\n"
2973 "#ifdef USEGLOW\n"
2974 "uniform sampler Texture_Glow : register(s3),\n"
2975 "#endif\n"
2976 "#ifdef USEVERTEXTEXTUREBLEND\n"
2977 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2978 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2979 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2980 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2981 "#endif\n"
2982 "#ifdef USEGLOW\n"
2983 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2984 "#endif\n"
2985 "#endif\n"
2986 "#ifdef USECOLORMAPPING\n"
2987 "uniform sampler Texture_Pants : register(s4),\n"
2988 "uniform sampler Texture_Shirt : register(s7),\n"
2989 "#endif\n"
2990 "#ifdef USEFOG\n"
2991 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2992 "uniform sampler Texture_FogMask : register(s8),\n"
2993 "#endif\n"
2994 "#ifdef USELIGHTMAP\n"
2995 "uniform sampler Texture_Lightmap : register(s9),\n"
2996 "#endif\n"
2997 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2998 "uniform sampler Texture_Deluxemap : register(s10),\n"
2999 "#endif\n"
3000 "#ifdef USEREFLECTION\n"
3001 "uniform sampler Texture_Reflection : register(s7),\n"
3002 "#endif\n"
3003 "\n"
3004 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3005 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3006 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3007 "#endif\n"
3008 "#ifdef USEDEFERREDLIGHTMAP\n"
3009 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3010 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3011 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
3012 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
3013 "#endif\n"
3014 "\n"
3015 "#ifdef USECOLORMAPPING\n"
3016 "uniform half3 Color_Pants : register(c7),\n"
3017 "uniform half3 Color_Shirt : register(c8),\n"
3018 "#endif\n"
3019 "#ifdef USEFOG\n"
3020 "uniform float3 FogColor : register(c16),\n"
3021 "uniform float FogRangeRecip : register(c20),\n"
3022 "uniform float FogPlaneViewDist : register(c19),\n"
3023 "uniform float FogHeightFade : register(c17),\n"
3024 "#endif\n"
3025 "\n"
3026 "#ifdef USEOFFSETMAPPING\n"
3027 "uniform float OffsetMapping_Scale : register(c24),\n"
3028 "#endif\n"
3029 "\n"
3030 "#ifdef USEDEFERREDLIGHTMAP\n"
3031 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3032 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3033 "uniform half3 DeferredMod_Specular : register(c13),\n"
3034 "#endif\n"
3035 "uniform half3 Color_Ambient : register(c3),\n"
3036 "uniform half3 Color_Diffuse : register(c4),\n"
3037 "uniform half3 Color_Specular : register(c5),\n"
3038 "uniform half SpecularPower : register(c36),\n"
3039 "#ifdef USEGLOW\n"
3040 "uniform half3 Color_Glow : register(c6),\n"
3041 "#endif\n"
3042 "uniform half Alpha : register(c0),\n"
3043 "#ifdef USEREFLECTION\n"
3044 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3045 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3046 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3047 "uniform half4 ReflectColor : register(c26),\n"
3048 "#endif\n"
3049 "#ifdef USEREFLECTCUBE\n"
3050 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3051 "uniform sampler Texture_ReflectMask : register(s5),\n"
3052 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3053 "#endif\n"
3054 "#ifdef MODE_LIGHTDIRECTION\n"
3055 "uniform half3 LightColor : register(c21),\n"
3056 "#endif\n"
3057 "#ifdef MODE_LIGHTSOURCE\n"
3058 "uniform half3 LightColor : register(c21),\n"
3059 "#endif\n"
3060 "\n"
3061 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3062 "uniform sampler Texture_Attenuation : register(s9),\n"
3063 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3064 "#endif\n"
3065 "\n"
3066 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3067 "\n"
3068 "#ifdef USESHADOWMAP2D\n"
3069 "# ifdef USESHADOWSAMPLER\n"
3070 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3071 "# else\n"
3072 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3073 "# endif\n"
3074 "#endif\n"
3075 "\n"
3076 "#ifdef USESHADOWMAPVSDCT\n"
3077 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3078 "#endif\n"
3079 "\n"
3080 "#if defined(USESHADOWMAP2D)\n"
3081 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3082 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3083 "#endif\n"
3084 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3085 "\n"
3086 "out float4 gl_FragColor : COLOR\n"
3087 ")\n"
3088 "{\n"
3089 "       float2 TexCoord = TexCoordBoth.xy;\n"
3090 "#ifdef USEVERTEXTEXTUREBLEND\n"
3091 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3092 "#endif\n"
3093 "#ifdef USEOFFSETMAPPING\n"
3094 "       // apply offsetmapping\n"
3095 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3096 "#define TexCoord TexCoordOffset\n"
3097 "#endif\n"
3098 "\n"
3099 "       // combine the diffuse textures (base, pants, shirt)\n"
3100 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3101 "#ifdef USEALPHAKILL\n"
3102 "       if (color.a < 0.5)\n"
3103 "               discard;\n"
3104 "#endif\n"
3105 "       color.a *= Alpha;\n"
3106 "#ifdef USECOLORMAPPING\n"
3107 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3108 "#endif\n"
3109 "#ifdef USEVERTEXTEXTUREBLEND\n"
3110 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3111 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3112 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3113 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3114 "       color.a = 1.0;\n"
3115 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3116 "#endif\n"
3117 "\n"
3118 "       // get the surface normal\n"
3119 "#ifdef USEVERTEXTEXTUREBLEND\n"
3120 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3121 "#else\n"
3122 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3123 "#endif\n"
3124 "\n"
3125 "       // get the material colors\n"
3126 "       half3 diffusetex = color.rgb;\n"
3127 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3128 "# ifdef USEVERTEXTEXTUREBLEND\n"
3129 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3130 "# else\n"
3131 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3132 "# endif\n"
3133 "#endif\n"
3134 "\n"
3135 "#ifdef USEREFLECTCUBE\n"
3136 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3137 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3138 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3139 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3140 "#endif\n"
3141 "\n"
3142 "\n"
3143 "\n"
3144 "\n"
3145 "#ifdef MODE_LIGHTSOURCE\n"
3146 "       // light source\n"
3147 "#ifdef USEDIFFUSE\n"
3148 "       half3 lightnormal = half3(normalize(LightVector));\n"
3149 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3150 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3151 "#ifdef USESPECULAR\n"
3152 "#ifdef USEEXACTSPECULARMATH\n"
3153 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3154 "#else\n"
3155 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3156 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3157 "#endif\n"
3158 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3159 "#endif\n"
3160 "#else\n"
3161 "       color.rgb = diffusetex * Color_Ambient;\n"
3162 "#endif\n"
3163 "       color.rgb *= LightColor;\n"
3164 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3165 "#if defined(USESHADOWMAP2D)\n"
3166 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3167 "#ifdef USESHADOWMAPVSDCT\n"
3168 ", Texture_CubeProjection\n"
3169 "#endif\n"
3170 "       ));\n"
3171 "\n"
3172 "#endif\n"
3173 "# ifdef USECUBEFILTER\n"
3174 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3175 "# endif\n"
3176 "\n"
3177 "#ifdef USESHADOWMAP2D\n"
3178 "#ifdef USESHADOWMAPVSDCT\n"
3179 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3180 "#else\n"
3181 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3182 "#endif\n"
3183 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3184 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3185 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3186 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3187 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3188 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3189 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3190 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3191 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3192 "//     color.r = half(shadowmaptc.z);\n"
3193 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3194 "//     color.r = half(shadowmaptc.z);\n"
3195 "//     color.r = 1;\n"
3196 "//     color.rgb = abs(CubeVector);\n"
3197 "#endif\n"
3198 "//     color.rgb = half3(1,1,1);\n"
3199 "#endif // MODE_LIGHTSOURCE\n"
3200 "\n"
3201 "\n"
3202 "\n"
3203 "\n"
3204 "#ifdef MODE_LIGHTDIRECTION\n"
3205 "#define SHADING\n"
3206 "#ifdef USEDIFFUSE\n"
3207 "       half3 lightnormal = half3(normalize(LightVector));\n"
3208 "#endif\n"
3209 "#define lightcolor LightColor\n"
3210 "#endif // MODE_LIGHTDIRECTION\n"
3211 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3212 "#define SHADING\n"
3213 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3214 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3215 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3216 "       // convert modelspace light vector to tangentspace\n"
3217 "       half3 lightnormal;\n"
3218 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3219 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3220 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3221 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3222 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3223 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3224 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3225 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3226 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3227 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3228 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3229 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3230 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3231 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3232 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3233 "#define SHADING\n"
3234 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3235 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3236 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3237 "#endif\n"
3238 "\n"
3239 "\n"
3240 "\n"
3241 "\n"
3242 "#ifdef MODE_FAKELIGHT\n"
3243 "#define SHADING\n"
3244 "half3 lightnormal = half3(normalize(EyeVector));\n"
3245 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3246 "#endif // MODE_FAKELIGHT\n"
3247 "\n"
3248 "\n"
3249 "\n"
3250 "\n"
3251 "#ifdef MODE_LIGHTMAP\n"
3252 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3253 "#endif // MODE_LIGHTMAP\n"
3254 "#ifdef MODE_VERTEXCOLOR\n"
3255 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3256 "#endif // MODE_VERTEXCOLOR\n"
3257 "#ifdef MODE_FLATCOLOR\n"
3258 "       color.rgb = diffusetex * Color_Ambient;\n"
3259 "#endif // MODE_FLATCOLOR\n"
3260 "\n"
3261 "\n"
3262 "\n"
3263 "\n"
3264 "#ifdef SHADING\n"
3265 "# ifdef USEDIFFUSE\n"
3266 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3267 "#  ifdef USESPECULAR\n"
3268 "#   ifdef USEEXACTSPECULARMATH\n"
3269 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3270 "#   else\n"
3271 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3272 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3273 "#   endif\n"
3274 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3275 "#  else\n"
3276 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3277 "#  endif\n"
3278 "# else\n"
3279 "       color.rgb = diffusetex * Color_Ambient;\n"
3280 "# endif\n"
3281 "#endif\n"
3282 "\n"
3283 "#ifdef USESHADOWMAPORTHO\n"
3284 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3285 "#endif\n"
3286 "\n"
3287 "#ifdef USEDEFERREDLIGHTMAP\n"
3288 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3289 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3290 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3291 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3292 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3293 "#endif\n"
3294 "\n"
3295 "#ifdef USEGLOW\n"
3296 "#ifdef USEVERTEXTEXTUREBLEND\n"
3297 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3298 "#else\n"
3299 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3300 "#endif\n"
3301 "#endif\n"
3302 "\n"
3303 "#ifdef USEFOG\n"
3304 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3305 "#endif\n"
3306 "\n"
3307 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
3308 "#ifdef USEREFLECTION\n"
3309 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3310 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3311 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3312 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3313 "       // FIXME temporary hack to detect the case that the reflection\n"
3314 "       // gets blackened at edges due to leaving the area that contains actual\n"
3315 "       // content.\n"
3316 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3317 "       // 'appening.\n"
3318 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3319 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3320 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3321 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3322 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3323 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3324 "#endif\n"
3325 "\n"
3326 "       gl_FragColor = float4(color);\n"
3327 "}\n"
3328 "#endif // FRAGMENT_SHADER\n"
3329 "\n"
3330 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3331 "#endif // !MODE_DEFERREDGEOMETRY\n"
3332 "#endif // !MODE_WATER\n"
3333 "#endif // !MODE_REFRACTION\n"
3334 "#endif // !MODE_BLOOMBLUR\n"
3335 "#endif // !MODE_GENERIC\n"
3336 "#endif // !MODE_POSTPROCESS\n"
3337 "#endif // !MODE_SHOWDEPTH\n"
3338 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3339 ;
3340
3341 char *glslshaderstring = NULL;
3342 char *hlslshaderstring = NULL;
3343
3344 //=======================================================================================================================================================
3345
3346 typedef struct shaderpermutationinfo_s
3347 {
3348         const char *pretext;
3349         const char *name;
3350 }
3351 shaderpermutationinfo_t;
3352
3353 typedef struct shadermodeinfo_s
3354 {
3355         const char *vertexfilename;
3356         const char *geometryfilename;
3357         const char *fragmentfilename;
3358         const char *pretext;
3359         const char *name;
3360 }
3361 shadermodeinfo_t;
3362
3363 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3364 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3365 {
3366         {"#define USEDIFFUSE\n", " diffuse"},
3367         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3368         {"#define USEVIEWTINT\n", " viewtint"},
3369         {"#define USECOLORMAPPING\n", " colormapping"},
3370         {"#define USESATURATION\n", " saturation"},
3371         {"#define USEFOGINSIDE\n", " foginside"},
3372         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3373         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3374         {"#define USEGAMMARAMPS\n", " gammaramps"},
3375         {"#define USECUBEFILTER\n", " cubefilter"},
3376         {"#define USEGLOW\n", " glow"},
3377         {"#define USEBLOOM\n", " bloom"},
3378         {"#define USESPECULAR\n", " specular"},
3379         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3380         {"#define USEREFLECTION\n", " reflection"},
3381         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3382         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3383         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3384         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3385         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3386         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3387         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3388         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3389         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3390         {"#define USEALPHAKILL\n", " alphakill"},
3391         {"#define USEREFLECTCUBE\n", " reflectcube"},
3392         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3393 };
3394
3395 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3396 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3397 {
3398         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3399         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3400         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3401         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3402         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3403         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3404         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3405         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3406         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3407         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3408         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3409         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3410         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3411         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3412         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3413         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3414 };
3415
3416 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3417 {
3418         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3419         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3420         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3421         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3422         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3423         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3424         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3425         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3426         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3427         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3428         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3429         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3430         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3431         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3432         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3433         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3434 };
3435
3436 struct r_glsl_permutation_s;
3437 typedef struct r_glsl_permutation_s
3438 {
3439         /// hash lookup data
3440         struct r_glsl_permutation_s *hashnext;
3441         unsigned int mode;
3442         unsigned int permutation;
3443
3444         /// indicates if we have tried compiling this permutation already
3445         qboolean compiled;
3446         /// 0 if compilation failed
3447         int program;
3448         // texture units assigned to each detected uniform
3449         int tex_Texture_First;
3450         int tex_Texture_Second;
3451         int tex_Texture_GammaRamps;
3452         int tex_Texture_Normal;
3453         int tex_Texture_Color;
3454         int tex_Texture_Gloss;
3455         int tex_Texture_Glow;
3456         int tex_Texture_SecondaryNormal;
3457         int tex_Texture_SecondaryColor;
3458         int tex_Texture_SecondaryGloss;
3459         int tex_Texture_SecondaryGlow;
3460         int tex_Texture_Pants;
3461         int tex_Texture_Shirt;
3462         int tex_Texture_FogHeightTexture;
3463         int tex_Texture_FogMask;
3464         int tex_Texture_Lightmap;
3465         int tex_Texture_Deluxemap;
3466         int tex_Texture_Attenuation;
3467         int tex_Texture_Cube;
3468         int tex_Texture_Refraction;
3469         int tex_Texture_Reflection;
3470         int tex_Texture_ShadowMap2D;
3471         int tex_Texture_CubeProjection;
3472         int tex_Texture_ScreenDepth;
3473         int tex_Texture_ScreenNormalMap;
3474         int tex_Texture_ScreenDiffuse;
3475         int tex_Texture_ScreenSpecular;
3476         int tex_Texture_ReflectMask;
3477         int tex_Texture_ReflectCube;
3478         /// locations of detected uniforms in program object, or -1 if not found
3479         int loc_Texture_First;
3480         int loc_Texture_Second;
3481         int loc_Texture_GammaRamps;
3482         int loc_Texture_Normal;
3483         int loc_Texture_Color;
3484         int loc_Texture_Gloss;
3485         int loc_Texture_Glow;
3486         int loc_Texture_SecondaryNormal;
3487         int loc_Texture_SecondaryColor;
3488         int loc_Texture_SecondaryGloss;
3489         int loc_Texture_SecondaryGlow;
3490         int loc_Texture_Pants;
3491         int loc_Texture_Shirt;
3492         int loc_Texture_FogHeightTexture;
3493         int loc_Texture_FogMask;
3494         int loc_Texture_Lightmap;
3495         int loc_Texture_Deluxemap;
3496         int loc_Texture_Attenuation;
3497         int loc_Texture_Cube;
3498         int loc_Texture_Refraction;
3499         int loc_Texture_Reflection;
3500         int loc_Texture_ShadowMap2D;
3501         int loc_Texture_CubeProjection;
3502         int loc_Texture_ScreenDepth;
3503         int loc_Texture_ScreenNormalMap;
3504         int loc_Texture_ScreenDiffuse;
3505         int loc_Texture_ScreenSpecular;
3506         int loc_Texture_ReflectMask;
3507         int loc_Texture_ReflectCube;
3508         int loc_Alpha;
3509         int loc_BloomBlur_Parameters;
3510         int loc_ClientTime;
3511         int loc_Color_Ambient;
3512         int loc_Color_Diffuse;
3513         int loc_Color_Specular;
3514         int loc_Color_Glow;
3515         int loc_Color_Pants;
3516         int loc_Color_Shirt;
3517         int loc_DeferredColor_Ambient;
3518         int loc_DeferredColor_Diffuse;
3519         int loc_DeferredColor_Specular;
3520         int loc_DeferredMod_Diffuse;
3521         int loc_DeferredMod_Specular;
3522         int loc_DistortScaleRefractReflect;
3523         int loc_EyePosition;
3524         int loc_FogColor;
3525         int loc_FogHeightFade;
3526         int loc_FogPlane;
3527         int loc_FogPlaneViewDist;
3528         int loc_FogRangeRecip;
3529         int loc_LightColor;
3530         int loc_LightDir;
3531         int loc_LightPosition;
3532         int loc_OffsetMapping_Scale;
3533         int loc_PixelSize;
3534         int loc_ReflectColor;
3535         int loc_ReflectFactor;
3536         int loc_ReflectOffset;
3537         int loc_RefractColor;
3538         int loc_Saturation;
3539         int loc_ScreenCenterRefractReflect;
3540         int loc_ScreenScaleRefractReflect;
3541         int loc_ScreenToDepth;
3542         int loc_ShadowMap_Parameters;
3543         int loc_ShadowMap_TextureScale;
3544         int loc_SpecularPower;
3545         int loc_UserVec1;
3546         int loc_UserVec2;
3547         int loc_UserVec3;
3548         int loc_UserVec4;
3549         int loc_ViewTintColor;
3550         int loc_ViewToLight;
3551         int loc_ModelToLight;
3552         int loc_TexMatrix;
3553         int loc_BackgroundTexMatrix;
3554         int loc_ModelViewProjectionMatrix;
3555         int loc_ModelViewMatrix;
3556         int loc_PixelToScreenTexCoord;
3557         int loc_ModelToReflectCube;
3558         int loc_ShadowMapMatrix;
3559         int loc_BloomColorSubtract;
3560         int loc_NormalmapScrollBlend;
3561 }
3562 r_glsl_permutation_t;
3563
3564 #define SHADERPERMUTATION_HASHSIZE 256
3565
3566
3567 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3568 // these can NOT degrade! only use for simple stuff
3569 enum
3570 {
3571         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3572         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3573         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3574         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3575         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3576         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
3577 };
3578 #define SHADERSTATICPARMS_COUNT 6
3579
3580 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3581 static int shaderstaticparms_count = 0;
3582
3583 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3584 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3585 qboolean R_CompileShader_CheckStaticParms(void)
3586 {
3587         static int r_compileshader_staticparms_save[1];
3588         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3589         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3590
3591         // detect all
3592         if (r_glsl_saturation_redcompensate.integer)
3593                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3594         if (r_shadow_glossexact.integer)
3595                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3596         if (r_glsl_postprocess.integer)
3597         {
3598                 if (r_glsl_postprocess_uservec1_enable.integer)
3599                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3600                 if (r_glsl_postprocess_uservec2_enable.integer)
3601                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3602                 if (r_glsl_postprocess_uservec3_enable.integer)
3603                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3604                 if (r_glsl_postprocess_uservec4_enable.integer)
3605                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3606         }
3607         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3608 }
3609
3610 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3611         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3612                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3613         else \
3614                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3615 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3616 {
3617         shaderstaticparms_count = 0;
3618
3619         // emit all
3620         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3621         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3622         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3623         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3624         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3625         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3626 }
3627
3628 /// information about each possible shader permutation
3629 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3630 /// currently selected permutation
3631 r_glsl_permutation_t *r_glsl_permutation;
3632 /// storage for permutations linked in the hash table
3633 memexpandablearray_t r_glsl_permutationarray;
3634
3635 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3636 {
3637         //unsigned int hashdepth = 0;
3638         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3639         r_glsl_permutation_t *p;
3640         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3641         {
3642                 if (p->mode == mode && p->permutation == permutation)
3643                 {
3644                         //if (hashdepth > 10)
3645                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3646                         return p;
3647                 }
3648                 //hashdepth++;
3649         }
3650         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3651         p->mode = mode;
3652         p->permutation = permutation;
3653         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3654         r_glsl_permutationhash[mode][hashindex] = p;
3655         //if (hashdepth > 10)
3656         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3657         return p;
3658 }
3659
3660 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3661 {
3662         char *shaderstring;
3663         if (!filename || !filename[0])
3664                 return NULL;
3665         if (!strcmp(filename, "glsl/default.glsl"))
3666         {
3667                 if (!glslshaderstring)
3668                 {
3669                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3670                         if (glslshaderstring)
3671                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3672                         else
3673                                 glslshaderstring = (char *)builtinshaderstring;
3674                 }
3675                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3676                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3677                 return shaderstring;
3678         }
3679         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3680         if (shaderstring)
3681         {
3682                 if (printfromdisknotice)
3683                         Con_DPrintf("from disk %s... ", filename);
3684                 return shaderstring;
3685         }
3686         return shaderstring;
3687 }
3688
3689 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3690 {
3691         int i;
3692         int sampler;
3693         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3694         char *vertexstring, *geometrystring, *fragmentstring;
3695         char permutationname[256];
3696         int vertstrings_count = 0;
3697         int geomstrings_count = 0;
3698         int fragstrings_count = 0;
3699         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3700         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3701         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3702
3703         if (p->compiled)
3704                 return;
3705         p->compiled = true;
3706         p->program = 0;
3707
3708         permutationname[0] = 0;
3709         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3710         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3711         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3712
3713         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3714
3715         // the first pretext is which type of shader to compile as
3716         // (later these will all be bound together as a program object)
3717         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3718         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3719         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3720
3721         // the second pretext is the mode (for example a light source)
3722         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3723         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3724         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3725         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3726
3727         // now add all the permutation pretexts
3728         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3729         {
3730                 if (permutation & (1<<i))
3731                 {
3732                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3733                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3734                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3735                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3736                 }
3737                 else
3738                 {
3739                         // keep line numbers correct
3740                         vertstrings_list[vertstrings_count++] = "\n";
3741                         geomstrings_list[geomstrings_count++] = "\n";
3742                         fragstrings_list[fragstrings_count++] = "\n";
3743                 }
3744         }
3745
3746         // add static parms
3747         R_CompileShader_AddStaticParms(mode, permutation);
3748         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3749         vertstrings_count += shaderstaticparms_count;
3750         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3751         geomstrings_count += shaderstaticparms_count;
3752         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3753         fragstrings_count += shaderstaticparms_count;
3754
3755         // now append the shader text itself
3756         vertstrings_list[vertstrings_count++] = vertexstring;
3757         geomstrings_list[geomstrings_count++] = geometrystring;
3758         fragstrings_list[fragstrings_count++] = fragmentstring;
3759
3760         // if any sources were NULL, clear the respective list
3761         if (!vertexstring)
3762                 vertstrings_count = 0;
3763         if (!geometrystring)
3764                 geomstrings_count = 0;
3765         if (!fragmentstring)
3766                 fragstrings_count = 0;
3767
3768         // compile the shader program
3769         if (vertstrings_count + geomstrings_count + fragstrings_count)
3770                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3771         if (p->program)
3772         {
3773                 CHECKGLERROR
3774                 qglUseProgram(p->program);CHECKGLERROR
3775                 // look up all the uniform variable names we care about, so we don't
3776                 // have to look them up every time we set them
3777
3778                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
3779                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
3780                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
3781                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
3782                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
3783                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
3784                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
3785                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
3786                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
3787                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
3788                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
3789                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
3790                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
3791                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
3792                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
3793                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
3794                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
3795                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
3796                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
3797                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
3798                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
3799                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
3800                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
3801                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
3802                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
3803                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
3804                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
3805                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
3806                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
3807                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
3808                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
3809                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
3810                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
3811                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
3812                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
3813                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
3814                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
3815                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
3816                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
3817                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
3818                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
3819                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
3820                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
3821                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
3822                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
3823                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
3824                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
3825                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
3826                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
3827                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
3828                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
3829                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
3830                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
3831                 p->loc_OffsetMapping_Scale        = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
3832                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
3833                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
3834                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
3835                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
3836                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
3837                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
3838                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
3839                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
3840                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
3841                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
3842                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
3843                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
3844                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
3845                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
3846                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
3847                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
3848                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
3849                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
3850                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
3851                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
3852                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
3853                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
3854                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
3855                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
3856                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
3857                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
3858                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
3859                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
3860                 // initialize the samplers to refer to the texture units we use
3861                 p->tex_Texture_First = -1;
3862                 p->tex_Texture_Second = -1;
3863                 p->tex_Texture_GammaRamps = -1;
3864                 p->tex_Texture_Normal = -1;
3865                 p->tex_Texture_Color = -1;
3866                 p->tex_Texture_Gloss = -1;
3867                 p->tex_Texture_Glow = -1;
3868                 p->tex_Texture_SecondaryNormal = -1;
3869                 p->tex_Texture_SecondaryColor = -1;
3870                 p->tex_Texture_SecondaryGloss = -1;
3871                 p->tex_Texture_SecondaryGlow = -1;
3872                 p->tex_Texture_Pants = -1;
3873                 p->tex_Texture_Shirt = -1;
3874                 p->tex_Texture_FogHeightTexture = -1;
3875                 p->tex_Texture_FogMask = -1;
3876                 p->tex_Texture_Lightmap = -1;
3877                 p->tex_Texture_Deluxemap = -1;
3878                 p->tex_Texture_Attenuation = -1;
3879                 p->tex_Texture_Cube = -1;
3880                 p->tex_Texture_Refraction = -1;
3881                 p->tex_Texture_Reflection = -1;
3882                 p->tex_Texture_ShadowMap2D = -1;
3883                 p->tex_Texture_CubeProjection = -1;
3884                 p->tex_Texture_ScreenDepth = -1;
3885                 p->tex_Texture_ScreenNormalMap = -1;
3886                 p->tex_Texture_ScreenDiffuse = -1;
3887                 p->tex_Texture_ScreenSpecular = -1;
3888                 p->tex_Texture_ReflectMask = -1;
3889                 p->tex_Texture_ReflectCube = -1;
3890                 sampler = 0;
3891                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
3892                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
3893                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
3894                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
3895                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
3896                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
3897                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
3898                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
3899                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
3900                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
3901                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
3902                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
3903                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
3904                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
3905                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
3906                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
3907                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
3908                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
3909                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
3910                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
3911                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
3912                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
3913                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
3914                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
3915                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
3916                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
3917                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
3918                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
3919                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
3920                 CHECKGLERROR
3921                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
3922         }
3923         else
3924                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3925
3926         // free the strings
3927         if (vertexstring)
3928                 Mem_Free(vertexstring);
3929         if (geometrystring)
3930                 Mem_Free(geometrystring);
3931         if (fragmentstring)
3932                 Mem_Free(fragmentstring);
3933 }
3934
3935 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3936 {
3937         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3938         if (r_glsl_permutation != perm)
3939         {
3940                 r_glsl_permutation = perm;
3941                 if (!r_glsl_permutation->program)
3942                 {
3943                         if (!r_glsl_permutation->compiled)
3944                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3945                         if (!r_glsl_permutation->program)
3946                         {
3947                                 // remove features until we find a valid permutation
3948                                 int i;
3949                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3950                                 {
3951                                         // reduce i more quickly whenever it would not remove any bits
3952                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3953                                         if (!(permutation & j))
3954                                                 continue;
3955                                         permutation -= j;
3956                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3957                                         if (!r_glsl_permutation->compiled)
3958                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3959                                         if (r_glsl_permutation->program)
3960                                                 break;
3961                                 }
3962                                 if (i >= SHADERPERMUTATION_COUNT)
3963                                 {
3964                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3965                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3966                                         qglUseProgram(0);CHECKGLERROR
3967                                         return; // no bit left to clear, entire mode is broken
3968                                 }
3969                         }
3970                 }
3971                 CHECKGLERROR
3972                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
3973         }
3974         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3975         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3976         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
3977 }
3978
3979 #ifdef SUPPORTD3D
3980
3981 #ifdef SUPPORTD3D
3982 #include <d3d9.h>
3983 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
3984 extern D3DCAPS9 vid_d3d9caps;
3985 #endif
3986
3987 struct r_hlsl_permutation_s;
3988 typedef struct r_hlsl_permutation_s
3989 {
3990         /// hash lookup data
3991         struct r_hlsl_permutation_s *hashnext;
3992         unsigned int mode;
3993         unsigned int permutation;
3994
3995         /// indicates if we have tried compiling this permutation already
3996         qboolean compiled;
3997         /// NULL if compilation failed
3998         IDirect3DVertexShader9 *vertexshader;
3999         IDirect3DPixelShader9 *pixelshader;
4000 }
4001 r_hlsl_permutation_t;
4002
4003 typedef enum D3DVSREGISTER_e
4004 {
4005         D3DVSREGISTER_TexMatrix = 0, // float4x4
4006         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4007         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4008         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4009         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4010         D3DVSREGISTER_ModelToLight = 20, // float4x4
4011         D3DVSREGISTER_EyePosition = 24,
4012         D3DVSREGISTER_FogPlane = 25,
4013         D3DVSREGISTER_LightDir = 26,
4014         D3DVSREGISTER_LightPosition = 27,
4015 }
4016 D3DVSREGISTER_t;
4017
4018 typedef enum D3DPSREGISTER_e
4019 {
4020         D3DPSREGISTER_Alpha = 0,
4021         D3DPSREGISTER_BloomBlur_Parameters = 1,
4022         D3DPSREGISTER_ClientTime = 2,
4023         D3DPSREGISTER_Color_Ambient = 3,
4024         D3DPSREGISTER_Color_Diffuse = 4,
4025         D3DPSREGISTER_Color_Specular = 5,
4026         D3DPSREGISTER_Color_Glow = 6,
4027         D3DPSREGISTER_Color_Pants = 7,
4028         D3DPSREGISTER_Color_Shirt = 8,
4029         D3DPSREGISTER_DeferredColor_Ambient = 9,
4030         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4031         D3DPSREGISTER_DeferredColor_Specular = 11,
4032         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4033         D3DPSREGISTER_DeferredMod_Specular = 13,
4034         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4035         D3DPSREGISTER_EyePosition = 15, // unused
4036         D3DPSREGISTER_FogColor = 16,
4037         D3DPSREGISTER_FogHeightFade = 17,
4038         D3DPSREGISTER_FogPlane = 18,
4039         D3DPSREGISTER_FogPlaneViewDist = 19,
4040         D3DPSREGISTER_FogRangeRecip = 20,
4041         D3DPSREGISTER_LightColor = 21,
4042         D3DPSREGISTER_LightDir = 22, // unused
4043         D3DPSREGISTER_LightPosition = 23,
4044         D3DPSREGISTER_OffsetMapping_Scale = 24,
4045         D3DPSREGISTER_PixelSize = 25,
4046         D3DPSREGISTER_ReflectColor = 26,
4047         D3DPSREGISTER_ReflectFactor = 27,
4048         D3DPSREGISTER_ReflectOffset = 28,
4049         D3DPSREGISTER_RefractColor = 29,
4050         D3DPSREGISTER_Saturation = 30,
4051         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4052         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4053         D3DPSREGISTER_ScreenToDepth = 33,
4054         D3DPSREGISTER_ShadowMap_Parameters = 34,
4055         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4056         D3DPSREGISTER_SpecularPower = 36,
4057         D3DPSREGISTER_UserVec1 = 37,
4058         D3DPSREGISTER_UserVec2 = 38,
4059         D3DPSREGISTER_UserVec3 = 39,
4060         D3DPSREGISTER_UserVec4 = 40,
4061         D3DPSREGISTER_ViewTintColor = 41,
4062         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4063         D3DPSREGISTER_BloomColorSubtract = 43,
4064         D3DPSREGISTER_ViewToLight = 44, // float4x4
4065         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4066         D3DPSREGISTER_NormalmapScrollBlend = 52,
4067         // next at 53
4068 }
4069 D3DPSREGISTER_t;
4070
4071 /// information about each possible shader permutation
4072 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4073 /// currently selected permutation
4074 r_hlsl_permutation_t *r_hlsl_permutation;
4075 /// storage for permutations linked in the hash table
4076 memexpandablearray_t r_hlsl_permutationarray;
4077
4078 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4079 {
4080         //unsigned int hashdepth = 0;
4081         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4082         r_hlsl_permutation_t *p;
4083         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4084         {
4085                 if (p->mode == mode && p->permutation == permutation)
4086                 {
4087                         //if (hashdepth > 10)
4088                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4089                         return p;
4090                 }
4091                 //hashdepth++;
4092         }
4093         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4094         p->mode = mode;
4095         p->permutation = permutation;
4096         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4097         r_hlsl_permutationhash[mode][hashindex] = p;
4098         //if (hashdepth > 10)
4099         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4100         return p;
4101 }
4102
4103 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4104 {
4105         char *shaderstring;
4106         if (!filename || !filename[0])
4107                 return NULL;
4108         if (!strcmp(filename, "hlsl/default.hlsl"))
4109         {
4110                 if (!hlslshaderstring)
4111                 {
4112                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4113                         if (hlslshaderstring)
4114                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4115                         else
4116                                 hlslshaderstring = (char *)builtinhlslshaderstring;
4117                 }
4118                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4119                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4120                 return shaderstring;
4121         }
4122         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4123         if (shaderstring)
4124         {
4125                 if (printfromdisknotice)
4126                         Con_DPrintf("from disk %s... ", filename);
4127                 return shaderstring;
4128         }
4129         return shaderstring;
4130 }
4131
4132 #include <d3dx9.h>
4133 //#include <d3dx9shader.h>
4134 //#include <d3dx9mesh.h>
4135
4136 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4137 {
4138         DWORD *vsbin = NULL;
4139         DWORD *psbin = NULL;
4140         fs_offset_t vsbinsize;
4141         fs_offset_t psbinsize;
4142 //      IDirect3DVertexShader9 *vs = NULL;
4143 //      IDirect3DPixelShader9 *ps = NULL;
4144         ID3DXBuffer *vslog = NULL;
4145         ID3DXBuffer *vsbuffer = NULL;
4146         ID3DXConstantTable *vsconstanttable = NULL;
4147         ID3DXBuffer *pslog = NULL;
4148         ID3DXBuffer *psbuffer = NULL;
4149         ID3DXConstantTable *psconstanttable = NULL;
4150         int vsresult = 0;
4151         int psresult = 0;
4152         char temp[MAX_INPUTLINE];
4153         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4154         qboolean debugshader = gl_paranoid.integer != 0;
4155         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4156         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4157         if (!debugshader)
4158         {
4159                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4160                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4161         }
4162         if ((!vsbin && vertstring) || (!psbin && fragstring))
4163         {
4164                 const char* dllnames_d3dx9 [] =
4165                 {
4166                         "d3dx9_43.dll",
4167                         "d3dx9_42.dll",
4168                         "d3dx9_41.dll",
4169                         "d3dx9_40.dll",
4170                         "d3dx9_39.dll",
4171                         "d3dx9_38.dll",
4172                         "d3dx9_37.dll",
4173                         "d3dx9_36.dll",
4174                         "d3dx9_35.dll",
4175                         "d3dx9_34.dll",
4176                         "d3dx9_33.dll",
4177                         "d3dx9_32.dll",
4178                         "d3dx9_31.dll",
4179                         "d3dx9_30.dll",
4180                         "d3dx9_29.dll",
4181                         "d3dx9_28.dll",
4182                         "d3dx9_27.dll",
4183                         "d3dx9_26.dll",
4184                         "d3dx9_25.dll",
4185                         "d3dx9_24.dll",
4186                         NULL
4187                 };
4188                 dllhandle_t d3dx9_dll = NULL;
4189                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4190                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4191                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4192                 dllfunction_t d3dx9_dllfuncs[] =
4193                 {
4194                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4195                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4196                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4197                         {NULL, NULL}
4198                 };
4199                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4200                 {
4201                         DWORD shaderflags = 0;
4202                         if (debugshader)
4203                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4204                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4205                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4206                         if (vertstring && vertstring[0])
4207                         {
4208                                 if (debugshader)
4209                                 {
4210 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4211 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4212                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4213                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4214                                 }
4215                                 else
4216                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4217                                 if (vsbuffer)
4218                                 {
4219                                         vsbinsize = vsbuffer->GetBufferSize();
4220                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4221                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4222                                         vsbuffer->Release();
4223                                 }
4224                                 if (vslog)
4225                                 {
4226                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4227                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4228                                         vslog->Release();
4229                                 }
4230                         }
4231                         if (fragstring && fragstring[0])
4232                         {
4233                                 if (debugshader)
4234                                 {
4235 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4236 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4237                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4238                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4239                                 }
4240                                 else
4241                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4242                                 if (psbuffer)
4243                                 {
4244                                         psbinsize = psbuffer->GetBufferSize();
4245                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4246                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4247                                         psbuffer->Release();
4248                                 }
4249                                 if (pslog)
4250                                 {
4251                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4252                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4253                                         pslog->Release();
4254                                 }
4255                         }
4256                         Sys_UnloadLibrary(&d3dx9_dll);
4257                 }
4258                 else
4259                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4260         }
4261         if (vsbin && psbin)
4262         {
4263                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4264                 if (FAILED(vsresult))
4265                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4266                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4267                 if (FAILED(psresult))
4268                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4269         }
4270         // free the shader data
4271         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4272         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4273 }
4274
4275 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4276 {
4277         int i;
4278         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4279         int vertstring_length = 0;
4280         int geomstring_length = 0;
4281         int fragstring_length = 0;
4282         char *t;
4283         char *vertexstring, *geometrystring, *fragmentstring;
4284         char *vertstring, *geomstring, *fragstring;
4285         char permutationname[256];
4286         char cachename[256];
4287         int vertstrings_count = 0;
4288         int geomstrings_count = 0;
4289         int fragstrings_count = 0;
4290         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4291         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4292         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4293
4294         if (p->compiled)
4295                 return;
4296         p->compiled = true;
4297         p->vertexshader = NULL;
4298         p->pixelshader = NULL;
4299
4300         permutationname[0] = 0;
4301         cachename[0] = 0;
4302         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4303         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4304         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4305
4306         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4307         strlcat(cachename, "hlsl/", sizeof(cachename));
4308
4309         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4310         vertstrings_count = 0;
4311         geomstrings_count = 0;
4312         fragstrings_count = 0;
4313         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4314         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4315         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4316
4317         // the first pretext is which type of shader to compile as
4318         // (later these will all be bound together as a program object)
4319         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4320         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4321         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4322
4323         // the second pretext is the mode (for example a light source)
4324         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4325         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4326         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4327         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4328         strlcat(cachename, modeinfo->name, sizeof(cachename));
4329
4330         // now add all the permutation pretexts
4331         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4332         {
4333                 if (permutation & (1<<i))
4334                 {
4335                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4336                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4337                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4338                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4339                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4340                 }
4341                 else
4342                 {
4343                         // keep line numbers correct
4344                         vertstrings_list[vertstrings_count++] = "\n";
4345                         geomstrings_list[geomstrings_count++] = "\n";
4346                         fragstrings_list[fragstrings_count++] = "\n";
4347                 }
4348         }
4349
4350         // add static parms
4351         R_CompileShader_AddStaticParms(mode, permutation);
4352         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4353         vertstrings_count += shaderstaticparms_count;
4354         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4355         geomstrings_count += shaderstaticparms_count;
4356         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4357         fragstrings_count += shaderstaticparms_count;
4358
4359         // replace spaces in the cachename with _ characters
4360         for (i = 0;cachename[i];i++)
4361                 if (cachename[i] == ' ')
4362                         cachename[i] = '_';
4363
4364         // now append the shader text itself
4365         vertstrings_list[vertstrings_count++] = vertexstring;
4366         geomstrings_list[geomstrings_count++] = geometrystring;
4367         fragstrings_list[fragstrings_count++] = fragmentstring;
4368
4369         // if any sources were NULL, clear the respective list
4370         if (!vertexstring)
4371                 vertstrings_count = 0;
4372         if (!geometrystring)
4373                 geomstrings_count = 0;
4374         if (!fragmentstring)
4375                 fragstrings_count = 0;
4376
4377         vertstring_length = 0;
4378         for (i = 0;i < vertstrings_count;i++)
4379                 vertstring_length += strlen(vertstrings_list[i]);
4380         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4381         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4382                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4383
4384         geomstring_length = 0;
4385         for (i = 0;i < geomstrings_count;i++)
4386                 geomstring_length += strlen(geomstrings_list[i]);
4387         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4388         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4389                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4390
4391         fragstring_length = 0;
4392         for (i = 0;i < fragstrings_count;i++)
4393                 fragstring_length += strlen(fragstrings_list[i]);
4394         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4395         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4396                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4397
4398         // try to load the cached shader, or generate one
4399         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4400
4401         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4402                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4403         else
4404                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4405
4406         // free the strings
4407         if (vertstring)
4408                 Mem_Free(vertstring);
4409         if (geomstring)
4410                 Mem_Free(geomstring);
4411         if (fragstring)
4412                 Mem_Free(fragstring);
4413         if (vertexstring)
4414                 Mem_Free(vertexstring);
4415         if (geometrystring)
4416                 Mem_Free(geometrystring);
4417         if (fragmentstring)
4418                 Mem_Free(fragmentstring);
4419 }
4420
4421 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4422 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4423 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);}
4424 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);}
4425 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);}
4426 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);}
4427
4428 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4429 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4430 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);}
4431 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);}
4432 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);}
4433 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);}
4434
4435 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4436 {
4437         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4438         if (r_hlsl_permutation != perm)
4439         {
4440                 r_hlsl_permutation = perm;
4441                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4442                 {
4443                         if (!r_hlsl_permutation->compiled)
4444                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4445                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4446                         {
4447                                 // remove features until we find a valid permutation
4448                                 int i;
4449                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4450                                 {
4451                                         // reduce i more quickly whenever it would not remove any bits
4452                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4453                                         if (!(permutation & j))
4454                                                 continue;
4455                                         permutation -= j;
4456                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4457                                         if (!r_hlsl_permutation->compiled)
4458                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4459                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4460                                                 break;
4461                                 }
4462                                 if (i >= SHADERPERMUTATION_COUNT)
4463                                 {
4464                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4465                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4466                                         return; // no bit left to clear, entire mode is broken
4467                                 }
4468                         }
4469                 }
4470                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4471                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4472         }
4473         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4474         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4475         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4476 }
4477 #endif
4478
4479 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
4480 {
4481         DPSOFTRAST_SetShader(mode, permutation);
4482         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
4483         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
4484         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
4485 }
4486
4487 void R_GLSL_Restart_f(void)
4488 {
4489         unsigned int i, limit;
4490         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4491                 Mem_Free(glslshaderstring);
4492         glslshaderstring = NULL;
4493         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
4494                 Mem_Free(hlslshaderstring);
4495         hlslshaderstring = NULL;
4496         switch(vid.renderpath)
4497         {
4498         case RENDERPATH_D3D9:
4499 #ifdef SUPPORTD3D
4500                 {
4501                         r_hlsl_permutation_t *p;
4502                         r_hlsl_permutation = NULL;
4503                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4504                         for (i = 0;i < limit;i++)
4505                         {
4506                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4507                                 {
4508                                         if (p->vertexshader)
4509                                                 IDirect3DVertexShader9_Release(p->vertexshader);
4510                                         if (p->pixelshader)
4511                                                 IDirect3DPixelShader9_Release(p->pixelshader);
4512                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4513                                 }
4514                         }
4515                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4516                 }
4517 #endif
4518                 break;
4519         case RENDERPATH_D3D10:
4520                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4521                 break;
4522         case RENDERPATH_D3D11:
4523                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4524                 break;
4525         case RENDERPATH_GL20:
4526         case RENDERPATH_GLES2:
4527                 {
4528                         r_glsl_permutation_t *p;
4529                         r_glsl_permutation = NULL;
4530                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4531                         for (i = 0;i < limit;i++)
4532                         {
4533                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4534                                 {
4535                                         GL_Backend_FreeProgram(p->program);
4536                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4537                                 }
4538                         }
4539                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4540                 }
4541                 break;
4542         case RENDERPATH_GL13:
4543         case RENDERPATH_GL11:
4544                 break;
4545         case RENDERPATH_SOFT:
4546                 break;
4547         }
4548 }
4549
4550 void R_GLSL_DumpShader_f(void)
4551 {
4552         int i;
4553         qfile_t *file;
4554
4555         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4556         if (file)
4557         {
4558                 FS_Print(file, "/* The engine may define the following macros:\n");
4559                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4560                 for (i = 0;i < SHADERMODE_COUNT;i++)
4561                         FS_Print(file, glslshadermodeinfo[i].pretext);
4562                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4563                         FS_Print(file, shaderpermutationinfo[i].pretext);
4564                 FS_Print(file, "*/\n");
4565                 FS_Print(file, builtinshaderstring);
4566                 FS_Close(file);
4567                 Con_Printf("glsl/default.glsl written\n");
4568         }
4569         else
4570                 Con_Printf("failed to write to glsl/default.glsl\n");
4571
4572         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
4573         if (file)
4574         {
4575                 FS_Print(file, "/* The engine may define the following macros:\n");
4576                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4577                 for (i = 0;i < SHADERMODE_COUNT;i++)
4578                         FS_Print(file, hlslshadermodeinfo[i].pretext);
4579                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4580                         FS_Print(file, shaderpermutationinfo[i].pretext);
4581                 FS_Print(file, "*/\n");
4582                 FS_Print(file, builtinhlslshaderstring);
4583                 FS_Close(file);
4584                 Con_Printf("hlsl/default.hlsl written\n");
4585         }
4586         else
4587                 Con_Printf("failed to write to hlsl/default.hlsl\n");
4588 }
4589
4590 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4591 {
4592         if (!second)
4593                 texturemode = GL_MODULATE;
4594         switch (vid.renderpath)
4595         {
4596         case RENDERPATH_D3D9:
4597 #ifdef SUPPORTD3D
4598                 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))));
4599                 R_Mesh_TexBind(GL20TU_FIRST , first );
4600                 R_Mesh_TexBind(GL20TU_SECOND, second);
4601 #endif
4602                 break;
4603         case RENDERPATH_D3D10:
4604                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4605                 break;
4606         case RENDERPATH_D3D11:
4607                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4608                 break;
4609         case RENDERPATH_GL20:
4610         case RENDERPATH_GLES2:
4611                 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))));
4612                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
4613                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
4614                 break;
4615         case RENDERPATH_GL13:
4616                 R_Mesh_TexBind(0, first );
4617                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4618                 R_Mesh_TexBind(1, second);
4619                 if (second)
4620                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4621                 break;
4622         case RENDERPATH_GL11:
4623                 R_Mesh_TexBind(0, first );
4624                 break;
4625         case RENDERPATH_SOFT:
4626                 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))));
4627                 R_Mesh_TexBind(GL20TU_FIRST , first );
4628                 R_Mesh_TexBind(GL20TU_SECOND, second);
4629                 break;
4630         }
4631 }
4632
4633 void R_SetupShader_DepthOrShadow(void)
4634 {
4635         switch (vid.renderpath)
4636         {
4637         case RENDERPATH_D3D9:
4638 #ifdef SUPPORTD3D
4639                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4640 #endif
4641                 break;
4642         case RENDERPATH_D3D10:
4643                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4644                 break;
4645         case RENDERPATH_D3D11:
4646                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4647                 break;
4648         case RENDERPATH_GL20:
4649         case RENDERPATH_GLES2:
4650                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4651                 break;
4652         case RENDERPATH_GL13:
4653                 R_Mesh_TexBind(0, 0);
4654                 R_Mesh_TexBind(1, 0);
4655                 break;
4656         case RENDERPATH_GL11:
4657                 R_Mesh_TexBind(0, 0);
4658                 break;
4659         case RENDERPATH_SOFT:
4660                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
4661                 break;
4662         }
4663 }
4664
4665 void R_SetupShader_ShowDepth(void)
4666 {
4667         switch (vid.renderpath)
4668         {
4669         case RENDERPATH_D3D9:
4670 #ifdef SUPPORTHLSL
4671                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
4672 #endif
4673                 break;
4674         case RENDERPATH_D3D10:
4675                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4676                 break;
4677         case RENDERPATH_D3D11:
4678                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4679                 break;
4680         case RENDERPATH_GL20:
4681         case RENDERPATH_GLES2:
4682                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4683                 break;
4684         case RENDERPATH_GL13:
4685                 break;
4686         case RENDERPATH_GL11:
4687                 break;
4688         case RENDERPATH_SOFT:
4689                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
4690                 break;
4691         }
4692 }
4693
4694 extern qboolean r_shadow_usingdeferredprepass;
4695 extern cvar_t r_shadow_deferred_8bitrange;
4696 extern rtexture_t *r_shadow_attenuationgradienttexture;
4697 extern rtexture_t *r_shadow_attenuation2dtexture;
4698 extern rtexture_t *r_shadow_attenuation3dtexture;
4699 extern qboolean r_shadow_usingshadowmap2d;
4700 extern qboolean r_shadow_usingshadowmaportho;
4701 extern float r_shadow_shadowmap_texturescale[2];
4702 extern float r_shadow_shadowmap_parameters[4];
4703 extern qboolean r_shadow_shadowmapvsdct;
4704 extern qboolean r_shadow_shadowmapsampler;
4705 extern int r_shadow_shadowmappcf;
4706 extern rtexture_t *r_shadow_shadowmap2dtexture;
4707 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
4708 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4709 extern matrix4x4_t r_shadow_shadowmapmatrix;
4710 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4711 extern int r_shadow_prepass_width;
4712 extern int r_shadow_prepass_height;
4713 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4714 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4715 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
4716 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4717 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4718 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
4719 {
4720         // a blendfunc allows colormod if:
4721         // a) it can never keep the destination pixel invariant, or
4722         // b) it can keep the destination pixel invariant, and still can do so if colormodded
4723         // this is to prevent unintended side effects from colormod
4724
4725         // in formulas:
4726         // IF there is a (s, sa) for which for all (d, da),
4727         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4728         // THEN, for this (s, sa) and all (colormod, d, da):
4729         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
4730         // OBVIOUSLY, this means that
4731         //   s*colormod * src(s*colormod, d, sa, da) = 0
4732         //   dst(s*colormod, d, sa, da)              = 1
4733
4734         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
4735
4736         // main condition to leave dst color invariant:
4737         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4738         //   src == GL_ZERO:
4739         //     s * 0 + d * dst(s, d, sa, da) == d
4740         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4741         //       => colormod is a problem for GL_SRC_COLOR only
4742         //   src == GL_ONE:
4743         //     s + d * dst(s, d, sa, da) == d
4744         //       => s == 0
4745         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4746         //       => colormod is never problematic for these
4747         //   src == GL_SRC_COLOR:
4748         //     s*s + d * dst(s, d, sa, da) == d
4749         //       => s == 0
4750         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4751         //       => colormod is never problematic for these
4752         //   src == GL_ONE_MINUS_SRC_COLOR:
4753         //     s*(1-s) + d * dst(s, d, sa, da) == d
4754         //       => s == 0 or s == 1
4755         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4756         //       => colormod is a problem for GL_SRC_COLOR only
4757         //   src == GL_DST_COLOR
4758         //     s*d + d * dst(s, d, sa, da) == d
4759         //       => s == 1
4760         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4761         //       => colormod is always a problem
4762         //     or
4763         //       => s == 0
4764         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4765         //       => colormod is never problematic for these
4766         //       => BUT, we do not know s! We must assume it is problematic
4767         //       then... except in GL_ONE case, where we know all invariant
4768         //       cases are fine
4769         //   src == GL_ONE_MINUS_DST_COLOR
4770         //     s*(1-d) + d * dst(s, d, sa, da) == d
4771         //       => s == 0 (1-d is impossible to handle for our desired result)
4772         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4773         //       => colormod is never problematic for these
4774         //   src == GL_SRC_ALPHA
4775         //     s*sa + d * dst(s, d, sa, da) == d
4776         //       => s == 0, or sa == 0
4777         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4778         //       => colormod breaks in the case GL_SRC_COLOR only
4779         //   src == GL_ONE_MINUS_SRC_ALPHA
4780         //     s*(1-sa) + d * dst(s, d, sa, da) == d
4781         //       => s == 0, or sa == 1
4782         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4783         //       => colormod breaks in the case GL_SRC_COLOR only
4784         //   src == GL_DST_ALPHA
4785         //     s*da + d * dst(s, d, sa, da) == d
4786         //       => s == 0
4787         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4788         //       => colormod is never problematic for these
4789
4790         switch(src)
4791         {
4792                 case GL_ZERO:
4793                 case GL_ONE_MINUS_SRC_COLOR:
4794                 case GL_SRC_ALPHA:
4795                 case GL_ONE_MINUS_SRC_ALPHA:
4796                         if(dst == GL_SRC_COLOR)
4797                                 return false;
4798                         return true;
4799                 case GL_ONE:
4800                 case GL_SRC_COLOR:
4801                 case GL_ONE_MINUS_DST_COLOR:
4802                 case GL_DST_ALPHA:
4803                 case GL_ONE_MINUS_DST_ALPHA:
4804                         return true;
4805                 case GL_DST_COLOR:
4806                         if(dst == GL_ONE)
4807                                 return true;
4808                         return false;
4809                 default:
4810                         return false;
4811         }
4812 }
4813 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)
4814 {
4815         // select a permutation of the lighting shader appropriate to this
4816         // combination of texture, entity, light source, and fogging, only use the
4817         // minimum features necessary to avoid wasting rendering time in the
4818         // fragment shader on features that are not being used
4819         unsigned int permutation = 0;
4820         unsigned int mode = 0;
4821         qboolean allow_colormod;
4822         static float dummy_colormod[3] = {1, 1, 1};
4823         float *colormod = rsurface.colormod;
4824         float m16f[16];
4825         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
4826         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4827                 permutation |= SHADERPERMUTATION_ALPHAKILL;
4828         if (rsurfacepass == RSURFPASS_BACKGROUND)
4829         {
4830                 // distorted background
4831                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4832                 {
4833                         mode = SHADERMODE_WATER;
4834                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
4835                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
4836                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
4837                         {
4838                                 // this is the right thing to do for wateralpha
4839                                 GL_BlendFunc(GL_ONE, GL_ZERO);
4840                                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4841                         }
4842                         else
4843                         {
4844                                 // this is the right thing to do for entity alpha
4845                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4846                                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4847                         }
4848                 }
4849                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
4850                 {
4851                         mode = SHADERMODE_REFRACTION;
4852                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4853                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4854                 }
4855                 else
4856                 {
4857                         mode = SHADERMODE_GENERIC;
4858                         permutation |= SHADERPERMUTATION_DIFFUSE;
4859                         GL_BlendFunc(GL_ONE, GL_ZERO);
4860                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4861                 }
4862         }
4863         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4864         {
4865                 if (r_glsl_offsetmapping.integer)
4866                 {
4867                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4868                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4869                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4870                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4871                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4872                         {
4873                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4874                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4875                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4876                         }
4877                 }
4878                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4879                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4880                 // normalmap (deferred prepass), may use alpha test on diffuse
4881                 mode = SHADERMODE_DEFERREDGEOMETRY;
4882                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4883                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4884                 GL_BlendFunc(GL_ONE, GL_ZERO);
4885                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4886         }
4887         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4888         {
4889                 if (r_glsl_offsetmapping.integer)
4890                 {
4891                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4892                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4893                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4894                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4895                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4896                         {
4897                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4898                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4899                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4900                         }
4901                 }
4902                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4903                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4904                 // light source
4905                 mode = SHADERMODE_LIGHTSOURCE;
4906                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4907                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4908                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4909                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4910                 if (diffusescale > 0)
4911                         permutation |= SHADERPERMUTATION_DIFFUSE;
4912                 if (specularscale > 0)
4913                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4914                 if (r_refdef.fogenabled)
4915                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4916                 if (rsurface.texture->colormapping)
4917                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4918                 if (r_shadow_usingshadowmap2d)
4919                 {
4920                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4921                         if(r_shadow_shadowmapvsdct)
4922                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4923
4924                         if (r_shadow_shadowmapsampler)
4925                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4926                         if (r_shadow_shadowmappcf > 1)
4927                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4928                         else if (r_shadow_shadowmappcf)
4929                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4930                 }
4931                 if (rsurface.texture->reflectmasktexture)
4932                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4933                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4934                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
4935         }
4936         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4937         {
4938                 if (r_glsl_offsetmapping.integer)
4939                 {
4940                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4941                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4942                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4943                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4944                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4945                         {
4946                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4947                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4948                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4949                         }
4950                 }
4951                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4952                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4953                 // unshaded geometry (fullbright or ambient model lighting)
4954                 mode = SHADERMODE_FLATCOLOR;
4955                 ambientscale = diffusescale = specularscale = 0;
4956                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4957                         permutation |= SHADERPERMUTATION_GLOW;
4958                 if (r_refdef.fogenabled)
4959                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4960                 if (rsurface.texture->colormapping)
4961                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4962                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4963                 {
4964                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4965                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4966
4967                         if (r_shadow_shadowmapsampler)
4968                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4969                         if (r_shadow_shadowmappcf > 1)
4970                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4971                         else if (r_shadow_shadowmappcf)
4972                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4973                 }
4974                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4975                         permutation |= SHADERPERMUTATION_REFLECTION;
4976                 if (rsurface.texture->reflectmasktexture)
4977                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4978                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4979                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4980         }
4981         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4982         {
4983                 if (r_glsl_offsetmapping.integer)
4984                 {
4985                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4986                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4987                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4988                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4989                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4990                         {
4991                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4992                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4993                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4994                         }
4995                 }
4996                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4997                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4998                 // directional model lighting
4999                 mode = SHADERMODE_LIGHTDIRECTION;
5000                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5001                         permutation |= SHADERPERMUTATION_GLOW;
5002                 permutation |= SHADERPERMUTATION_DIFFUSE;
5003                 if (specularscale > 0)
5004                         permutation |= SHADERPERMUTATION_SPECULAR;
5005                 if (r_refdef.fogenabled)
5006                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5007                 if (rsurface.texture->colormapping)
5008                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5009                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5010                 {
5011                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5012                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5013
5014                         if (r_shadow_shadowmapsampler)
5015                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5016                         if (r_shadow_shadowmappcf > 1)
5017                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5018                         else if (r_shadow_shadowmappcf)
5019                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5020                 }
5021                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5022                         permutation |= SHADERPERMUTATION_REFLECTION;
5023                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5024                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5025                 if (rsurface.texture->reflectmasktexture)
5026                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5027                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5028                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5029         }
5030         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5031         {
5032                 if (r_glsl_offsetmapping.integer)
5033                 {
5034                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5035                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5036                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5037                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5038                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5039                         {
5040                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5041                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5042                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5043                         }
5044                 }
5045                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5046                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5047                 // ambient model lighting
5048                 mode = SHADERMODE_LIGHTDIRECTION;
5049                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5050                         permutation |= SHADERPERMUTATION_GLOW;
5051                 if (r_refdef.fogenabled)
5052                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5053                 if (rsurface.texture->colormapping)
5054                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5055                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5056                 {
5057                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5058                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5059
5060                         if (r_shadow_shadowmapsampler)
5061                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5062                         if (r_shadow_shadowmappcf > 1)
5063                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5064                         else if (r_shadow_shadowmappcf)
5065                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5066                 }
5067                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5068                         permutation |= SHADERPERMUTATION_REFLECTION;
5069                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5070                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5071                 if (rsurface.texture->reflectmasktexture)
5072                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5073                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5074                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5075         }
5076         else
5077         {
5078                 if (r_glsl_offsetmapping.integer)
5079                 {
5080                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5081                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5082                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5083                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5084                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5085                         {
5086                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5087                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5088                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5089                         }
5090                 }
5091                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5092                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5093                 // lightmapped wall
5094                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5095                         permutation |= SHADERPERMUTATION_GLOW;
5096                 if (r_refdef.fogenabled)
5097                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5098                 if (rsurface.texture->colormapping)
5099                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5100                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5101                 {
5102                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5103                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5104
5105                         if (r_shadow_shadowmapsampler)
5106                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5107                         if (r_shadow_shadowmappcf > 1)
5108                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5109                         else if (r_shadow_shadowmappcf)
5110                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5111                 }
5112                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5113                         permutation |= SHADERPERMUTATION_REFLECTION;
5114                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5115                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5116                 if (rsurface.texture->reflectmasktexture)
5117                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5118                 if (FAKELIGHT_ENABLED)
5119                 {
5120                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5121                         mode = SHADERMODE_FAKELIGHT;
5122                         permutation |= SHADERPERMUTATION_DIFFUSE;
5123                         if (specularscale > 0)
5124                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5125                 }
5126                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5127                 {
5128                         // deluxemapping (light direction texture)
5129                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5130                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5131                         else
5132                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5133                         permutation |= SHADERPERMUTATION_DIFFUSE;
5134                         if (specularscale > 0)
5135                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5136                 }
5137                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5138                 {
5139                         // fake deluxemapping (uniform light direction in tangentspace)
5140                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5141                         permutation |= SHADERPERMUTATION_DIFFUSE;
5142                         if (specularscale > 0)
5143                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5144                 }
5145                 else if (rsurface.uselightmaptexture)
5146                 {
5147                         // ordinary lightmapping (q1bsp, q3bsp)
5148                         mode = SHADERMODE_LIGHTMAP;
5149                 }
5150                 else
5151                 {
5152                         // ordinary vertex coloring (q3bsp)
5153                         mode = SHADERMODE_VERTEXCOLOR;
5154                 }
5155                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5156                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5157         }
5158         if(!allow_colormod)
5159                 colormod = dummy_colormod;
5160         switch(vid.renderpath)
5161         {
5162         case RENDERPATH_D3D9:
5163 #ifdef SUPPORTD3D
5164                 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);
5165                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5166                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5167                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5168                 if (mode == SHADERMODE_LIGHTSOURCE)
5169                 {
5170                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5171                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5172                 }
5173                 else
5174                 {
5175                         if (mode == SHADERMODE_LIGHTDIRECTION)
5176                         {
5177                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5178                         }
5179                 }
5180                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5181                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5182                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5183                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5184                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5185
5186                 if (mode == SHADERMODE_LIGHTSOURCE)
5187                 {
5188                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5189                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5190                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5191                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5192                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5193
5194                         // additive passes are only darkened by fog, not tinted
5195                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5196                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5197                 }
5198                 else
5199                 {
5200                         if (mode == SHADERMODE_FLATCOLOR)
5201                         {
5202                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5203                         }
5204                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5205                         {
5206                                 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]);
5207                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5208                                 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);
5209                                 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);
5210                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5211                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5212                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5213                         }
5214                         else
5215                         {
5216                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5217                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5218                                 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);
5219                                 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);
5220                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5221                         }
5222                         // additive passes are only darkened by fog, not tinted
5223                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5224                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5225                         else
5226                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5227                         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);
5228                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5229                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5230                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5231                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5232                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5233                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5234                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5235                         if (mode == SHADERMODE_WATER)
5236                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5237                 }
5238                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5239                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5240                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5241                 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));
5242                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5243                 if (rsurface.texture->pantstexture)
5244                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5245                 else
5246                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5247                 if (rsurface.texture->shirttexture)
5248                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5249                 else
5250                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5251                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5252                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5253                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5254                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5255                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5256                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5257                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5258
5259                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5260                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5261                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5262                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5263                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5264                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5265                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5266                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5267                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5268                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5269                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5270                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5271                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5272                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5273                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5274                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5275                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5276                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5277                 {
5278                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5279                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5280                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5281                 }
5282                 else
5283                 {
5284                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5285                 }
5286 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5287 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5288                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5289                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5290                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5291                 {
5292                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5293                         if (rsurface.rtlight)
5294                         {
5295                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5296                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5297                         }
5298                 }
5299 #endif
5300                 break;
5301         case RENDERPATH_D3D10:
5302                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5303                 break;
5304         case RENDERPATH_D3D11:
5305                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5306                 break;
5307         case RENDERPATH_GL20:
5308         case RENDERPATH_GLES2:
5309                 if (!vid.useinterleavedarrays)
5310                 {
5311                         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);
5312                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5313                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5314                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5315                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5316                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5317                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5318                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5319                 }
5320                 else
5321                 {
5322                         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);
5323                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5324                 }
5325                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5326                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5327                 if (mode == SHADERMODE_LIGHTSOURCE)
5328                 {
5329                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5330                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5331                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5332                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5333                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5334                         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);
5335         
5336                         // additive passes are only darkened by fog, not tinted
5337                         if (r_glsl_permutation->loc_FogColor >= 0)
5338                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5339                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5340                 }
5341                 else
5342                 {
5343                         if (mode == SHADERMODE_FLATCOLOR)
5344                         {
5345                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5346                         }
5347                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5348                         {
5349                                 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]);
5350                                 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]);
5351                                 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);
5352                                 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);
5353                                 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);
5354                                 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]);
5355                                 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]);
5356                         }
5357                         else
5358                         {
5359                                 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]);
5360                                 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]);
5361                                 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);
5362                                 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);
5363                                 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);
5364                         }
5365                         // additive passes are only darkened by fog, not tinted
5366                         if (r_glsl_permutation->loc_FogColor >= 0)
5367                         {
5368                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5369                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5370                                 else
5371                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5372                         }
5373                         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);
5374                         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]);
5375                         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]);
5376                         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]);
5377                         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]);
5378                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5379                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5380                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5381                         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]);
5382                 }
5383                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5384                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5385                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5386                 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]);
5387                 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]);
5388
5389                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5390                 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));
5391                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5392                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5393                 {
5394                         if (rsurface.texture->pantstexture)
5395                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5396                         else
5397                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5398                 }
5399                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5400                 {
5401                         if (rsurface.texture->shirttexture)
5402                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5403                         else
5404                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5405                 }
5406                 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]);
5407                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5408                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5409                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5410                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5411                 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]);
5412                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5413
5414                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
5415                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
5416                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
5417                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
5418                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
5419                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
5420                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
5421                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
5422                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
5423                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
5424                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
5425                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
5426                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
5427                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
5428                 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);
5429                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
5430                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
5431                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5432                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5433                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
5434                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5435                 {
5436                         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);
5437                         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);
5438                         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);
5439                 }
5440                 else
5441                 {
5442                         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);
5443                 }
5444                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
5445                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
5446                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
5447                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
5448                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5449                 {
5450                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
5451                         if (rsurface.rtlight)
5452                         {
5453                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
5454                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
5455                         }
5456                 }
5457                 CHECKGLERROR
5458                 break;
5459         case RENDERPATH_GL13:
5460         case RENDERPATH_GL11:
5461                 break;
5462         case RENDERPATH_SOFT:
5463                 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);
5464                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
5465                 R_SetupShader_SetPermutationSoft(mode, permutation);
5466                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
5467                 if (mode == SHADERMODE_LIGHTSOURCE)
5468                 {
5469                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
5470                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5471                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5472                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5473                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5474                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5475         
5476                         // additive passes are only darkened by fog, not tinted
5477                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5478                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5479                 }
5480                 else
5481                 {
5482                         if (mode == SHADERMODE_FLATCOLOR)
5483                         {
5484                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5485                         }
5486                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5487                         {
5488                                 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]);
5489                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5490                                 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);
5491                                 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);
5492                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5493                                 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]);
5494                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5495                         }
5496                         else
5497                         {
5498                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5499                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5500                                 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);
5501                                 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);
5502                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5503                         }
5504                         // additive passes are only darkened by fog, not tinted
5505                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5506                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5507                         else
5508                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5509                         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);
5510                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5511                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5512                         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]);
5513                         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]);
5514                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5515                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
5516                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5517                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5518                 }
5519                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
5520                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
5521                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
5522                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5523                 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]);
5524
5525                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5526                 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));
5527                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5528                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
5529                 {
5530                         if (rsurface.texture->pantstexture)
5531                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5532                         else
5533                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
5534                 }
5535                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
5536                 {
5537                         if (rsurface.texture->shirttexture)
5538                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5539                         else
5540                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
5541                 }
5542                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5543                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
5544                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
5545                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
5546                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5547                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5548                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5549
5550                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5551                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5552                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5553                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5554                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5555                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5556                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5557                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5558                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5559                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5560                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5561                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5562                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5563                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5564                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5565                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5566                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5567                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5568                 {
5569                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5570                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5571                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5572                 }
5573                 else
5574                 {
5575                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5576                 }
5577 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5578 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5579                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5580                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5581                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5582                 {
5583                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5584                         if (rsurface.rtlight)
5585                         {
5586                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5587                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5588                         }
5589                 }
5590                 break;
5591         }
5592 }
5593
5594 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5595 {
5596         // select a permutation of the lighting shader appropriate to this
5597         // combination of texture, entity, light source, and fogging, only use the
5598         // minimum features necessary to avoid wasting rendering time in the
5599         // fragment shader on features that are not being used
5600         unsigned int permutation = 0;
5601         unsigned int mode = 0;
5602         const float *lightcolorbase = rtlight->currentcolor;
5603         float ambientscale = rtlight->ambientscale;
5604         float diffusescale = rtlight->diffusescale;
5605         float specularscale = rtlight->specularscale;
5606         // this is the location of the light in view space
5607         vec3_t viewlightorigin;
5608         // this transforms from view space (camera) to light space (cubemap)
5609         matrix4x4_t viewtolight;
5610         matrix4x4_t lighttoview;
5611         float viewtolight16f[16];
5612         float range = 1.0f / r_shadow_deferred_8bitrange.value;
5613         // light source
5614         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5615         if (rtlight->currentcubemap != r_texture_whitecube)
5616                 permutation |= SHADERPERMUTATION_CUBEFILTER;
5617         if (diffusescale > 0)
5618                 permutation |= SHADERPERMUTATION_DIFFUSE;
5619         if (specularscale > 0)
5620                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5621         if (r_shadow_usingshadowmap2d)
5622         {
5623                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5624                 if (r_shadow_shadowmapvsdct)
5625                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5626
5627                 if (r_shadow_shadowmapsampler)
5628                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5629                 if (r_shadow_shadowmappcf > 1)
5630                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5631                 else if (r_shadow_shadowmappcf)
5632                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5633         }
5634         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5635         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5636         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5637         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5638         switch(vid.renderpath)
5639         {
5640         case RENDERPATH_D3D9:
5641 #ifdef SUPPORTD3D
5642                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5643                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5644                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
5645                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
5646                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
5647                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5648                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5649                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5650                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5651                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5652                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5653
5654                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5655                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
5656                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5657                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5658                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
5659                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5660 #endif
5661                 break;
5662         case RENDERPATH_D3D10:
5663                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5664                 break;
5665         case RENDERPATH_D3D11:
5666                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5667                 break;
5668         case RENDERPATH_GL20:
5669         case RENDERPATH_GLES2:
5670                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5671                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5672                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
5673                 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);
5674                 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);
5675                 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);
5676                 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]);
5677                 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]);
5678                 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));
5679                 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]);
5680                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
5681
5682                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
5683                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
5684                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
5685                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
5686                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
5687                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
5688                 break;
5689         case RENDERPATH_GL13:
5690         case RENDERPATH_GL11:
5691                 break;
5692         case RENDERPATH_SOFT:
5693                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5694                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5695                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
5696                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
5697                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
5698                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5699                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5700                 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]);
5701                 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));
5702                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5703                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5704
5705                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5706                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5707                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5708                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5709                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5710                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5711                 break;
5712         }
5713 }
5714
5715 #define SKINFRAME_HASH 1024
5716
5717 typedef struct
5718 {
5719         int loadsequence; // incremented each level change
5720         memexpandablearray_t array;
5721         skinframe_t *hash[SKINFRAME_HASH];
5722 }
5723 r_skinframe_t;
5724 r_skinframe_t r_skinframe;
5725
5726 void R_SkinFrame_PrepareForPurge(void)
5727 {
5728         r_skinframe.loadsequence++;
5729         // wrap it without hitting zero
5730         if (r_skinframe.loadsequence >= 200)
5731                 r_skinframe.loadsequence = 1;
5732 }
5733
5734 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5735 {
5736         if (!skinframe)
5737                 return;
5738         // mark the skinframe as used for the purging code
5739         skinframe->loadsequence = r_skinframe.loadsequence;
5740 }
5741
5742 void R_SkinFrame_Purge(void)
5743 {
5744         int i;
5745         skinframe_t *s;
5746         for (i = 0;i < SKINFRAME_HASH;i++)
5747         {
5748                 for (s = r_skinframe.hash[i];s;s = s->next)
5749                 {
5750                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5751                         {
5752                                 if (s->merged == s->base)
5753                                         s->merged = NULL;
5754                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5755                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5756                                 R_PurgeTexture(s->merged);s->merged = NULL;
5757                                 R_PurgeTexture(s->base  );s->base   = NULL;
5758                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5759                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5760                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5761                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5762                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5763                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5764                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
5765                                 s->loadsequence = 0;
5766                         }
5767                 }
5768         }
5769 }
5770
5771 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5772         skinframe_t *item;
5773         char basename[MAX_QPATH];
5774
5775         Image_StripImageExtension(name, basename, sizeof(basename));
5776
5777         if( last == NULL ) {
5778                 int hashindex;
5779                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5780                 item = r_skinframe.hash[hashindex];
5781         } else {
5782                 item = last->next;
5783         }
5784
5785         // linearly search through the hash bucket
5786         for( ; item ; item = item->next ) {
5787                 if( !strcmp( item->basename, basename ) ) {
5788                         return item;
5789                 }
5790         }
5791         return NULL;
5792 }
5793
5794 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5795 {
5796         skinframe_t *item;
5797         int hashindex;
5798         char basename[MAX_QPATH];
5799
5800         Image_StripImageExtension(name, basename, sizeof(basename));
5801
5802         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5803         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5804                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5805                         break;
5806
5807         if (!item) {
5808                 rtexture_t *dyntexture;
5809                 // check whether its a dynamic texture
5810                 dyntexture = CL_GetDynTexture( basename );
5811                 if (!add && !dyntexture)
5812                         return NULL;
5813                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5814                 memset(item, 0, sizeof(*item));
5815                 strlcpy(item->basename, basename, sizeof(item->basename));
5816                 item->base = dyntexture; // either NULL or dyntexture handle
5817                 item->textureflags = textureflags;
5818                 item->comparewidth = comparewidth;
5819                 item->compareheight = compareheight;
5820                 item->comparecrc = comparecrc;
5821                 item->next = r_skinframe.hash[hashindex];
5822                 r_skinframe.hash[hashindex] = item;
5823         }
5824         else if( item->base == NULL )
5825         {
5826                 rtexture_t *dyntexture;
5827                 // check whether its a dynamic texture
5828                 // 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]
5829                 dyntexture = CL_GetDynTexture( basename );
5830                 item->base = dyntexture; // either NULL or dyntexture handle
5831         }
5832
5833         R_SkinFrame_MarkUsed(item);
5834         return item;
5835 }
5836
5837 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5838         { \
5839                 unsigned long long avgcolor[5], wsum; \
5840                 int pix, comp, w; \
5841                 avgcolor[0] = 0; \
5842                 avgcolor[1] = 0; \
5843                 avgcolor[2] = 0; \
5844                 avgcolor[3] = 0; \
5845                 avgcolor[4] = 0; \
5846                 wsum = 0; \
5847                 for(pix = 0; pix < cnt; ++pix) \
5848                 { \
5849                         w = 0; \
5850                         for(comp = 0; comp < 3; ++comp) \
5851                                 w += getpixel; \
5852                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5853                         { \
5854                                 ++wsum; \
5855                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5856                                 w = getpixel; \
5857                                 for(comp = 0; comp < 3; ++comp) \
5858                                         avgcolor[comp] += getpixel * w; \
5859                                 avgcolor[3] += w; \
5860                         } \
5861                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5862                         avgcolor[4] += getpixel; \
5863                 } \
5864                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5865                         avgcolor[3] = 1; \
5866                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5867                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5868                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5869                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5870         }
5871
5872 extern cvar_t gl_picmip;
5873 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5874 {
5875         int j;
5876         unsigned char *pixels;
5877         unsigned char *bumppixels;
5878         unsigned char *basepixels = NULL;
5879         int basepixels_width = 0;
5880         int basepixels_height = 0;
5881         skinframe_t *skinframe;
5882         rtexture_t *ddsbase = NULL;
5883         qboolean ddshasalpha = false;
5884         float ddsavgcolor[4];
5885         char basename[MAX_QPATH];
5886         int miplevel = R_PicmipForFlags(textureflags);
5887         int savemiplevel = miplevel;
5888         int mymiplevel;
5889
5890         if (cls.state == ca_dedicated)
5891                 return NULL;
5892
5893         // return an existing skinframe if already loaded
5894         // if loading of the first image fails, don't make a new skinframe as it
5895         // would cause all future lookups of this to be missing
5896         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5897         if (skinframe && skinframe->base)
5898                 return skinframe;
5899
5900         Image_StripImageExtension(name, basename, sizeof(basename));
5901
5902         // check for DDS texture file first
5903         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
5904         {
5905                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
5906                 if (basepixels == NULL)
5907                         return NULL;
5908         }
5909
5910         // FIXME handle miplevel
5911
5912         if (developer_loading.integer)
5913                 Con_Printf("loading skin \"%s\"\n", name);
5914
5915         // we've got some pixels to store, so really allocate this new texture now
5916         if (!skinframe)
5917                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5918         skinframe->stain = NULL;
5919         skinframe->merged = NULL;
5920         skinframe->base = NULL;
5921         skinframe->pants = NULL;
5922         skinframe->shirt = NULL;
5923         skinframe->nmap = NULL;
5924         skinframe->gloss = NULL;
5925         skinframe->glow = NULL;
5926         skinframe->fog = NULL;
5927         skinframe->reflect = NULL;
5928         skinframe->hasalpha = false;
5929
5930         if (ddsbase)
5931         {
5932                 skinframe->base = ddsbase;
5933                 skinframe->hasalpha = ddshasalpha;
5934                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5935                 if (r_loadfog && skinframe->hasalpha)
5936                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
5937                 //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]);
5938         }
5939         else
5940         {
5941                 basepixels_width = image_width;
5942                 basepixels_height = image_height;
5943                 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);
5944                 if (textureflags & TEXF_ALPHA)
5945                 {
5946                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5947                         {
5948                                 if (basepixels[j] < 255)
5949                                 {
5950                                         skinframe->hasalpha = true;
5951                                         break;
5952                                 }
5953                         }
5954                         if (r_loadfog && skinframe->hasalpha)
5955                         {
5956                                 // has transparent pixels
5957                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5958                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5959                                 {
5960                                         pixels[j+0] = 255;
5961                                         pixels[j+1] = 255;
5962                                         pixels[j+2] = 255;
5963                                         pixels[j+3] = basepixels[j+3];
5964                                 }
5965                                 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);
5966                                 Mem_Free(pixels);
5967                         }
5968                 }
5969                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5970                 //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]);
5971                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5972                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
5973                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5974                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
5975         }
5976
5977         if (r_loaddds)
5978         {
5979                 mymiplevel = savemiplevel;
5980                 if (r_loadnormalmap)
5981                         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);
5982                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5983                 if (r_loadgloss)
5984                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5985                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5986                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5987                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5988         }
5989
5990         // _norm is the name used by tenebrae and has been adopted as standard
5991         if (r_loadnormalmap && skinframe->nmap == NULL)
5992         {
5993                 mymiplevel = savemiplevel;
5994                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
5995                 {
5996                         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);
5997                         Mem_Free(pixels);
5998                         pixels = NULL;
5999                 }
6000                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6001                 {
6002                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6003                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6004                         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);
6005                         Mem_Free(pixels);
6006                         Mem_Free(bumppixels);
6007                 }
6008                 else if (r_shadow_bumpscale_basetexture.value > 0)
6009                 {
6010                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6011                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6012                         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);
6013                         Mem_Free(pixels);
6014                 }
6015                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6016                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6017         }
6018
6019         // _luma is supported only for tenebrae compatibility
6020         // _glow is the preferred name
6021         mymiplevel = savemiplevel;
6022         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))))
6023         {
6024                 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);
6025                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6026                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6027                 Mem_Free(pixels);pixels = NULL;
6028         }
6029
6030         mymiplevel = savemiplevel;
6031         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6032         {
6033                 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);
6034                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6035                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6036                 Mem_Free(pixels);
6037                 pixels = NULL;
6038         }
6039
6040         mymiplevel = savemiplevel;
6041         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6042         {
6043                 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);
6044                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6045                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6046                 Mem_Free(pixels);
6047                 pixels = NULL;
6048         }
6049
6050         mymiplevel = savemiplevel;
6051         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6052         {
6053                 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);
6054                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6055                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6056                 Mem_Free(pixels);
6057                 pixels = NULL;
6058         }
6059
6060         mymiplevel = savemiplevel;
6061         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6062         {
6063                 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);
6064                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6065                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6066                 Mem_Free(pixels);
6067                 pixels = NULL;
6068         }
6069
6070         if (basepixels)
6071                 Mem_Free(basepixels);
6072
6073         return skinframe;
6074 }
6075
6076 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6077 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6078 {
6079         int i;
6080         unsigned char *temp1, *temp2;
6081         skinframe_t *skinframe;
6082
6083         if (cls.state == ca_dedicated)
6084                 return NULL;
6085
6086         // if already loaded just return it, otherwise make a new skinframe
6087         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6088         if (skinframe && skinframe->base)
6089                 return skinframe;
6090
6091         skinframe->stain = NULL;
6092         skinframe->merged = NULL;
6093         skinframe->base = NULL;
6094         skinframe->pants = NULL;
6095         skinframe->shirt = NULL;
6096         skinframe->nmap = NULL;
6097         skinframe->gloss = NULL;
6098         skinframe->glow = NULL;
6099         skinframe->fog = NULL;
6100         skinframe->reflect = NULL;
6101         skinframe->hasalpha = false;
6102
6103         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6104         if (!skindata)
6105                 return NULL;
6106
6107         if (developer_loading.integer)
6108                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6109
6110         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6111         {
6112                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6113                 temp2 = temp1 + width * height * 4;
6114                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6115                 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);
6116                 Mem_Free(temp1);
6117         }
6118         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6119         if (textureflags & TEXF_ALPHA)
6120         {
6121                 for (i = 3;i < width * height * 4;i += 4)
6122                 {
6123                         if (skindata[i] < 255)
6124                         {
6125                                 skinframe->hasalpha = true;
6126                                 break;
6127                         }
6128                 }
6129                 if (r_loadfog && skinframe->hasalpha)
6130                 {
6131                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6132                         memcpy(fogpixels, skindata, width * height * 4);
6133                         for (i = 0;i < width * height * 4;i += 4)
6134                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6135                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6136                         Mem_Free(fogpixels);
6137                 }
6138         }
6139
6140         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6141         //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]);
6142
6143         return skinframe;
6144 }
6145
6146 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6147 {
6148         int i;
6149         int featuresmask;
6150         skinframe_t *skinframe;
6151
6152         if (cls.state == ca_dedicated)
6153                 return NULL;
6154
6155         // if already loaded just return it, otherwise make a new skinframe
6156         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6157         if (skinframe && skinframe->base)
6158                 return skinframe;
6159
6160         skinframe->stain = NULL;
6161         skinframe->merged = NULL;
6162         skinframe->base = NULL;
6163         skinframe->pants = NULL;
6164         skinframe->shirt = NULL;
6165         skinframe->nmap = NULL;
6166         skinframe->gloss = NULL;
6167         skinframe->glow = NULL;
6168         skinframe->fog = NULL;
6169         skinframe->reflect = NULL;
6170         skinframe->hasalpha = false;
6171
6172         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6173         if (!skindata)
6174                 return NULL;
6175
6176         if (developer_loading.integer)
6177                 Con_Printf("loading quake skin \"%s\"\n", name);
6178
6179         // 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)
6180         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6181         memcpy(skinframe->qpixels, skindata, width*height);
6182         skinframe->qwidth = width;
6183         skinframe->qheight = height;
6184
6185         featuresmask = 0;
6186         for (i = 0;i < width * height;i++)
6187                 featuresmask |= palette_featureflags[skindata[i]];
6188
6189         skinframe->hasalpha = false;
6190         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6191         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6192         skinframe->qgeneratemerged = true;
6193         skinframe->qgeneratebase = skinframe->qhascolormapping;
6194         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6195
6196         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6197         //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]);
6198
6199         return skinframe;
6200 }
6201
6202 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6203 {
6204         int width;
6205         int height;
6206         unsigned char *skindata;
6207
6208         if (!skinframe->qpixels)
6209                 return;
6210
6211         if (!skinframe->qhascolormapping)
6212                 colormapped = false;
6213
6214         if (colormapped)
6215         {
6216                 if (!skinframe->qgeneratebase)
6217                         return;
6218         }
6219         else
6220         {
6221                 if (!skinframe->qgeneratemerged)
6222                         return;
6223         }
6224
6225         width = skinframe->qwidth;
6226         height = skinframe->qheight;
6227         skindata = skinframe->qpixels;
6228
6229         if (skinframe->qgeneratenmap)
6230         {
6231                 unsigned char *temp1, *temp2;
6232                 skinframe->qgeneratenmap = false;
6233                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6234                 temp2 = temp1 + width * height * 4;
6235                 // use either a custom palette or the quake palette
6236                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6237                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6238                 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);
6239                 Mem_Free(temp1);
6240         }
6241
6242         if (skinframe->qgenerateglow)
6243         {
6244                 skinframe->qgenerateglow = false;
6245                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6246         }
6247
6248         if (colormapped)
6249         {
6250                 skinframe->qgeneratebase = false;
6251                 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);
6252                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6253                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6254         }
6255         else
6256         {
6257                 skinframe->qgeneratemerged = false;
6258                 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);
6259         }
6260
6261         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6262         {
6263                 Mem_Free(skinframe->qpixels);
6264                 skinframe->qpixels = NULL;
6265         }
6266 }
6267
6268 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)
6269 {
6270         int i;
6271         skinframe_t *skinframe;
6272
6273         if (cls.state == ca_dedicated)
6274                 return NULL;
6275
6276         // if already loaded just return it, otherwise make a new skinframe
6277         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6278         if (skinframe && skinframe->base)
6279                 return skinframe;
6280
6281         skinframe->stain = NULL;
6282         skinframe->merged = NULL;
6283         skinframe->base = NULL;
6284         skinframe->pants = NULL;
6285         skinframe->shirt = NULL;
6286         skinframe->nmap = NULL;
6287         skinframe->gloss = NULL;
6288         skinframe->glow = NULL;
6289         skinframe->fog = NULL;
6290         skinframe->reflect = NULL;
6291         skinframe->hasalpha = false;
6292
6293         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6294         if (!skindata)
6295                 return NULL;
6296
6297         if (developer_loading.integer)
6298                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6299
6300         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6301         if (textureflags & TEXF_ALPHA)
6302         {
6303                 for (i = 0;i < width * height;i++)
6304                 {
6305                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6306                         {
6307                                 skinframe->hasalpha = true;
6308                                 break;
6309                         }
6310                 }
6311                 if (r_loadfog && skinframe->hasalpha)
6312                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6313         }
6314
6315         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6316         //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]);
6317
6318         return skinframe;
6319 }
6320
6321 skinframe_t *R_SkinFrame_LoadMissing(void)
6322 {
6323         skinframe_t *skinframe;
6324
6325         if (cls.state == ca_dedicated)
6326                 return NULL;
6327
6328         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6329         skinframe->stain = NULL;
6330         skinframe->merged = NULL;
6331         skinframe->base = NULL;
6332         skinframe->pants = NULL;
6333         skinframe->shirt = NULL;
6334         skinframe->nmap = NULL;
6335         skinframe->gloss = NULL;
6336         skinframe->glow = NULL;
6337         skinframe->fog = NULL;
6338         skinframe->reflect = NULL;
6339         skinframe->hasalpha = false;
6340
6341         skinframe->avgcolor[0] = rand() / RAND_MAX;
6342         skinframe->avgcolor[1] = rand() / RAND_MAX;
6343         skinframe->avgcolor[2] = rand() / RAND_MAX;
6344         skinframe->avgcolor[3] = 1;
6345
6346         return skinframe;
6347 }
6348
6349 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6350 typedef struct suffixinfo_s
6351 {
6352         const char *suffix;
6353         qboolean flipx, flipy, flipdiagonal;
6354 }
6355 suffixinfo_t;
6356 static suffixinfo_t suffix[3][6] =
6357 {
6358         {
6359                 {"px",   false, false, false},
6360                 {"nx",   false, false, false},
6361                 {"py",   false, false, false},
6362                 {"ny",   false, false, false},
6363                 {"pz",   false, false, false},
6364                 {"nz",   false, false, false}
6365         },
6366         {
6367                 {"posx", false, false, false},
6368                 {"negx", false, false, false},
6369                 {"posy", false, false, false},
6370                 {"negy", false, false, false},
6371                 {"posz", false, false, false},
6372                 {"negz", false, false, false}
6373         },
6374         {
6375                 {"rt",    true, false,  true},
6376                 {"lf",   false,  true,  true},
6377                 {"ft",    true,  true, false},
6378                 {"bk",   false, false, false},
6379                 {"up",    true, false,  true},
6380                 {"dn",    true, false,  true}
6381         }
6382 };
6383
6384 static int componentorder[4] = {0, 1, 2, 3};
6385
6386 rtexture_t *R_LoadCubemap(const char *basename)
6387 {
6388         int i, j, cubemapsize;
6389         unsigned char *cubemappixels, *image_buffer;
6390         rtexture_t *cubemaptexture;
6391         char name[256];
6392         // must start 0 so the first loadimagepixels has no requested width/height
6393         cubemapsize = 0;
6394         cubemappixels = NULL;
6395         cubemaptexture = NULL;
6396         // keep trying different suffix groups (posx, px, rt) until one loads
6397         for (j = 0;j < 3 && !cubemappixels;j++)
6398         {
6399                 // load the 6 images in the suffix group
6400                 for (i = 0;i < 6;i++)
6401                 {
6402                         // generate an image name based on the base and and suffix
6403                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6404                         // load it
6405                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6406                         {
6407                                 // an image loaded, make sure width and height are equal
6408                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6409                                 {
6410                                         // if this is the first image to load successfully, allocate the cubemap memory
6411                                         if (!cubemappixels && image_width >= 1)
6412                                         {
6413                                                 cubemapsize = image_width;
6414                                                 // note this clears to black, so unavailable sides are black
6415                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6416                                         }
6417                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6418                                         if (cubemappixels)
6419                                                 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);
6420                                 }
6421                                 else
6422                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6423                                 // free the image
6424                                 Mem_Free(image_buffer);
6425                         }
6426                 }
6427         }
6428         // if a cubemap loaded, upload it
6429         if (cubemappixels)
6430         {
6431                 if (developer_loading.integer)
6432                         Con_Printf("loading cubemap \"%s\"\n", basename);
6433
6434                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6435                 Mem_Free(cubemappixels);
6436         }
6437         else
6438         {
6439                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6440                 if (developer_loading.integer)
6441                 {
6442                         Con_Printf("(tried tried images ");
6443                         for (j = 0;j < 3;j++)
6444                                 for (i = 0;i < 6;i++)
6445                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6446                         Con_Print(" and was unable to find any of them).\n");
6447                 }
6448         }
6449         return cubemaptexture;
6450 }
6451
6452 rtexture_t *R_GetCubemap(const char *basename)
6453 {
6454         int i;
6455         for (i = 0;i < r_texture_numcubemaps;i++)
6456                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6457                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6458         if (i >= MAX_CUBEMAPS)
6459                 return r_texture_whitecube;
6460         r_texture_numcubemaps++;
6461         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6462         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6463         return r_texture_cubemaps[i].texture;
6464 }
6465
6466 void R_FreeCubemaps(void)
6467 {
6468         int i;
6469         for (i = 0;i < r_texture_numcubemaps;i++)
6470         {
6471                 if (developer_loading.integer)
6472                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6473                 if (r_texture_cubemaps[i].texture)
6474                         R_FreeTexture(r_texture_cubemaps[i].texture);
6475         }
6476         r_texture_numcubemaps = 0;
6477 }
6478
6479 void R_Main_FreeViewCache(void)
6480 {
6481         if (r_refdef.viewcache.entityvisible)
6482                 Mem_Free(r_refdef.viewcache.entityvisible);
6483         if (r_refdef.viewcache.world_pvsbits)
6484                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6485         if (r_refdef.viewcache.world_leafvisible)
6486                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6487         if (r_refdef.viewcache.world_surfacevisible)
6488                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6489         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6490 }
6491
6492 void R_Main_ResizeViewCache(void)
6493 {
6494         int numentities = r_refdef.scene.numentities;
6495         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6496         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6497         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6498         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6499         if (r_refdef.viewcache.maxentities < numentities)
6500         {
6501                 r_refdef.viewcache.maxentities = numentities;
6502                 if (r_refdef.viewcache.entityvisible)
6503                         Mem_Free(r_refdef.viewcache.entityvisible);
6504                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6505         }
6506         if (r_refdef.viewcache.world_numclusters != numclusters)
6507         {
6508                 r_refdef.viewcache.world_numclusters = numclusters;
6509                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6510                 if (r_refdef.viewcache.world_pvsbits)
6511                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6512                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6513         }
6514         if (r_refdef.viewcache.world_numleafs != numleafs)
6515         {
6516                 r_refdef.viewcache.world_numleafs = numleafs;
6517                 if (r_refdef.viewcache.world_leafvisible)
6518                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6519                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6520         }
6521         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6522         {
6523                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6524                 if (r_refdef.viewcache.world_surfacevisible)
6525                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6526                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6527         }
6528 }
6529
6530 extern rtexture_t *loadingscreentexture;
6531 void gl_main_start(void)
6532 {
6533         loadingscreentexture = NULL;
6534         r_texture_blanknormalmap = NULL;
6535         r_texture_white = NULL;
6536         r_texture_grey128 = NULL;
6537         r_texture_black = NULL;
6538         r_texture_whitecube = NULL;
6539         r_texture_normalizationcube = NULL;
6540         r_texture_fogattenuation = NULL;
6541         r_texture_fogheighttexture = NULL;
6542         r_texture_gammaramps = NULL;
6543         r_texture_numcubemaps = 0;
6544
6545         r_loaddds = r_texture_dds_load.integer != 0;
6546         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6547
6548         switch(vid.renderpath)
6549         {
6550         case RENDERPATH_GL20:
6551         case RENDERPATH_D3D9:
6552         case RENDERPATH_D3D10:
6553         case RENDERPATH_D3D11:
6554         case RENDERPATH_SOFT:
6555                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6556                 Cvar_SetValueQuick(&gl_combine, 1);
6557                 Cvar_SetValueQuick(&r_glsl, 1);
6558                 r_loadnormalmap = true;
6559                 r_loadgloss = true;
6560                 r_loadfog = false;
6561                 break;
6562         case RENDERPATH_GL13:
6563                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6564                 Cvar_SetValueQuick(&gl_combine, 1);
6565                 Cvar_SetValueQuick(&r_glsl, 0);
6566                 r_loadnormalmap = false;
6567                 r_loadgloss = false;
6568                 r_loadfog = true;
6569                 break;
6570         case RENDERPATH_GL11:
6571                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6572                 Cvar_SetValueQuick(&gl_combine, 0);
6573                 Cvar_SetValueQuick(&r_glsl, 0);
6574                 r_loadnormalmap = false;
6575                 r_loadgloss = false;
6576                 r_loadfog = true;
6577                 break;
6578         case RENDERPATH_GLES2:
6579                 Cvar_SetValueQuick(&r_textureunits, 1);
6580                 Cvar_SetValueQuick(&gl_combine, 1);
6581                 Cvar_SetValueQuick(&r_glsl, 1);
6582                 r_loadnormalmap = true;
6583                 r_loadgloss = false;
6584                 r_loadfog = false;
6585                 break;
6586         }
6587
6588         R_AnimCache_Free();
6589         R_FrameData_Reset();
6590
6591         r_numqueries = 0;
6592         r_maxqueries = 0;
6593         memset(r_queries, 0, sizeof(r_queries));
6594
6595         r_qwskincache = NULL;
6596         r_qwskincache_size = 0;
6597
6598         // set up r_skinframe loading system for textures
6599         memset(&r_skinframe, 0, sizeof(r_skinframe));
6600         r_skinframe.loadsequence = 1;
6601         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6602
6603         r_main_texturepool = R_AllocTexturePool();
6604         R_BuildBlankTextures();
6605         R_BuildNoTexture();
6606         if (vid.support.arb_texture_cube_map)
6607         {
6608                 R_BuildWhiteCube();
6609                 R_BuildNormalizationCube();
6610         }
6611         r_texture_fogattenuation = NULL;
6612         r_texture_fogheighttexture = NULL;
6613         r_texture_gammaramps = NULL;
6614         //r_texture_fogintensity = NULL;
6615         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6616         memset(&r_waterstate, 0, sizeof(r_waterstate));
6617         r_glsl_permutation = NULL;
6618         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6619         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6620         glslshaderstring = NULL;
6621 #ifdef SUPPORTD3D
6622         r_hlsl_permutation = NULL;
6623         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6624         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
6625 #endif
6626         hlslshaderstring = NULL;
6627         memset(&r_svbsp, 0, sizeof (r_svbsp));
6628
6629         r_refdef.fogmasktable_density = 0;
6630 }
6631
6632 void gl_main_shutdown(void)
6633 {
6634         R_AnimCache_Free();
6635         R_FrameData_Reset();
6636
6637         R_Main_FreeViewCache();
6638
6639         switch(vid.renderpath)
6640         {
6641         case RENDERPATH_GL11:
6642         case RENDERPATH_GL13:
6643         case RENDERPATH_GL20:
6644         case RENDERPATH_GLES2:
6645                 if (r_maxqueries)
6646                         qglDeleteQueriesARB(r_maxqueries, r_queries);
6647                 break;
6648         case RENDERPATH_D3D9:
6649                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6650                 break;
6651         case RENDERPATH_D3D10:
6652                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6653                 break;
6654         case RENDERPATH_D3D11:
6655                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6656                 break;
6657         case RENDERPATH_SOFT:
6658                 break;
6659         }
6660
6661         r_numqueries = 0;
6662         r_maxqueries = 0;
6663         memset(r_queries, 0, sizeof(r_queries));
6664
6665         r_qwskincache = NULL;
6666         r_qwskincache_size = 0;
6667
6668         // clear out the r_skinframe state
6669         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6670         memset(&r_skinframe, 0, sizeof(r_skinframe));
6671
6672         if (r_svbsp.nodes)
6673                 Mem_Free(r_svbsp.nodes);
6674         memset(&r_svbsp, 0, sizeof (r_svbsp));
6675         R_FreeTexturePool(&r_main_texturepool);
6676         loadingscreentexture = NULL;
6677         r_texture_blanknormalmap = NULL;
6678         r_texture_white = NULL;
6679         r_texture_grey128 = NULL;
6680         r_texture_black = NULL;
6681         r_texture_whitecube = NULL;
6682         r_texture_normalizationcube = NULL;
6683         r_texture_fogattenuation = NULL;
6684         r_texture_fogheighttexture = NULL;
6685         r_texture_gammaramps = NULL;
6686         r_texture_numcubemaps = 0;
6687         //r_texture_fogintensity = NULL;
6688         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6689         memset(&r_waterstate, 0, sizeof(r_waterstate));
6690         R_GLSL_Restart_f();
6691
6692         r_glsl_permutation = NULL;
6693         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6694         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
6695         glslshaderstring = NULL;
6696 #ifdef SUPPORTD3D
6697         r_hlsl_permutation = NULL;
6698         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6699         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
6700 #endif
6701         hlslshaderstring = NULL;
6702 }
6703
6704 extern void CL_ParseEntityLump(char *entitystring);
6705 void gl_main_newmap(void)
6706 {
6707         // FIXME: move this code to client
6708         char *entities, entname[MAX_QPATH];
6709         if (r_qwskincache)
6710                 Mem_Free(r_qwskincache);
6711         r_qwskincache = NULL;
6712         r_qwskincache_size = 0;
6713         if (cl.worldmodel)
6714         {
6715                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
6716                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6717                 {
6718                         CL_ParseEntityLump(entities);
6719                         Mem_Free(entities);
6720                         return;
6721                 }
6722                 if (cl.worldmodel->brush.entities)
6723                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
6724         }
6725         R_Main_FreeViewCache();
6726
6727         R_FrameData_Reset();
6728 }
6729
6730 void GL_Main_Init(void)
6731 {
6732         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6733
6734         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6735         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6736         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6737         if (gamemode == GAME_NEHAHRA)
6738         {
6739                 Cvar_RegisterVariable (&gl_fogenable);
6740                 Cvar_RegisterVariable (&gl_fogdensity);
6741                 Cvar_RegisterVariable (&gl_fogred);
6742                 Cvar_RegisterVariable (&gl_foggreen);
6743                 Cvar_RegisterVariable (&gl_fogblue);
6744                 Cvar_RegisterVariable (&gl_fogstart);
6745                 Cvar_RegisterVariable (&gl_fogend);
6746                 Cvar_RegisterVariable (&gl_skyclip);
6747         }
6748         Cvar_RegisterVariable(&r_motionblur);
6749         Cvar_RegisterVariable(&r_motionblur_maxblur);
6750         Cvar_RegisterVariable(&r_motionblur_bmin);
6751         Cvar_RegisterVariable(&r_motionblur_vmin);
6752         Cvar_RegisterVariable(&r_motionblur_vmax);
6753         Cvar_RegisterVariable(&r_motionblur_vcoeff);
6754         Cvar_RegisterVariable(&r_motionblur_randomize);
6755         Cvar_RegisterVariable(&r_damageblur);
6756         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6757         Cvar_RegisterVariable(&r_equalize_entities_minambient);
6758         Cvar_RegisterVariable(&r_equalize_entities_by);
6759         Cvar_RegisterVariable(&r_equalize_entities_to);
6760         Cvar_RegisterVariable(&r_depthfirst);
6761         Cvar_RegisterVariable(&r_useinfinitefarclip);
6762         Cvar_RegisterVariable(&r_farclip_base);
6763         Cvar_RegisterVariable(&r_farclip_world);
6764         Cvar_RegisterVariable(&r_nearclip);
6765         Cvar_RegisterVariable(&r_showbboxes);
6766         Cvar_RegisterVariable(&r_showsurfaces);
6767         Cvar_RegisterVariable(&r_showtris);
6768         Cvar_RegisterVariable(&r_shownormals);
6769         Cvar_RegisterVariable(&r_showlighting);
6770         Cvar_RegisterVariable(&r_showshadowvolumes);
6771         Cvar_RegisterVariable(&r_showcollisionbrushes);
6772         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6773         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6774         Cvar_RegisterVariable(&r_showdisabledepthtest);
6775         Cvar_RegisterVariable(&r_drawportals);
6776         Cvar_RegisterVariable(&r_drawentities);
6777         Cvar_RegisterVariable(&r_draw2d);
6778         Cvar_RegisterVariable(&r_drawworld);
6779         Cvar_RegisterVariable(&r_cullentities_trace);
6780         Cvar_RegisterVariable(&r_cullentities_trace_samples);
6781         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6782         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6783         Cvar_RegisterVariable(&r_cullentities_trace_delay);
6784         Cvar_RegisterVariable(&r_drawviewmodel);
6785         Cvar_RegisterVariable(&r_drawexteriormodel);
6786         Cvar_RegisterVariable(&r_speeds);
6787         Cvar_RegisterVariable(&r_fullbrights);
6788         Cvar_RegisterVariable(&r_wateralpha);
6789         Cvar_RegisterVariable(&r_dynamic);
6790         Cvar_RegisterVariable(&r_fakelight);
6791         Cvar_RegisterVariable(&r_fakelight_intensity);
6792         Cvar_RegisterVariable(&r_fullbright);
6793         Cvar_RegisterVariable(&r_shadows);
6794         Cvar_RegisterVariable(&r_shadows_darken);
6795         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6796         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6797         Cvar_RegisterVariable(&r_shadows_throwdistance);
6798         Cvar_RegisterVariable(&r_shadows_throwdirection);
6799         Cvar_RegisterVariable(&r_shadows_focus);
6800         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6801         Cvar_RegisterVariable(&r_q1bsp_skymasking);
6802         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6803         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6804         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6805         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6806         Cvar_RegisterVariable(&r_fog_exp2);
6807         Cvar_RegisterVariable(&r_drawfog);
6808         Cvar_RegisterVariable(&r_transparentdepthmasking);
6809         Cvar_RegisterVariable(&r_texture_dds_load);
6810         Cvar_RegisterVariable(&r_texture_dds_save);
6811         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6812         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6813         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6814         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6815         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6816         Cvar_RegisterVariable(&r_textureunits);
6817         Cvar_RegisterVariable(&gl_combine);
6818         Cvar_RegisterVariable(&r_glsl);
6819         Cvar_RegisterVariable(&r_glsl_deluxemapping);
6820         Cvar_RegisterVariable(&r_glsl_offsetmapping);
6821         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6822         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6823         Cvar_RegisterVariable(&r_glsl_postprocess);
6824         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6825         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6826         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6827         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6828         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
6829         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
6830         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
6831         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
6832
6833         Cvar_RegisterVariable(&r_water);
6834         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6835         Cvar_RegisterVariable(&r_water_clippingplanebias);
6836         Cvar_RegisterVariable(&r_water_refractdistort);
6837         Cvar_RegisterVariable(&r_water_reflectdistort);
6838         Cvar_RegisterVariable(&r_water_scissormode);
6839         Cvar_RegisterVariable(&r_lerpsprites);
6840         Cvar_RegisterVariable(&r_lerpmodels);
6841         Cvar_RegisterVariable(&r_lerplightstyles);
6842         Cvar_RegisterVariable(&r_waterscroll);
6843         Cvar_RegisterVariable(&r_bloom);
6844         Cvar_RegisterVariable(&r_bloom_colorscale);
6845         Cvar_RegisterVariable(&r_bloom_brighten);
6846         Cvar_RegisterVariable(&r_bloom_blur);
6847         Cvar_RegisterVariable(&r_bloom_resolution);
6848         Cvar_RegisterVariable(&r_bloom_colorexponent);
6849         Cvar_RegisterVariable(&r_bloom_colorsubtract);
6850         Cvar_RegisterVariable(&r_hdr);
6851         Cvar_RegisterVariable(&r_hdr_scenebrightness);
6852         Cvar_RegisterVariable(&r_hdr_glowintensity);
6853         Cvar_RegisterVariable(&r_hdr_range);
6854         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6855         Cvar_RegisterVariable(&developer_texturelogging);
6856         Cvar_RegisterVariable(&gl_lightmaps);
6857         Cvar_RegisterVariable(&r_test);
6858         Cvar_RegisterVariable(&r_glsl_saturation);
6859         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
6860         Cvar_RegisterVariable(&r_framedatasize);
6861         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6862                 Cvar_SetValue("r_fullbrights", 0);
6863         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
6864
6865         Cvar_RegisterVariable(&r_track_sprites);
6866         Cvar_RegisterVariable(&r_track_sprites_flags);
6867         Cvar_RegisterVariable(&r_track_sprites_scalew);
6868         Cvar_RegisterVariable(&r_track_sprites_scaleh);
6869         Cvar_RegisterVariable(&r_overheadsprites_perspective);
6870         Cvar_RegisterVariable(&r_overheadsprites_pushback);
6871         Cvar_RegisterVariable(&r_overheadsprites_scalex);
6872         Cvar_RegisterVariable(&r_overheadsprites_scaley);
6873 }
6874
6875 extern void R_Textures_Init(void);
6876 extern void GL_Draw_Init(void);
6877 extern void GL_Main_Init(void);
6878 extern void R_Shadow_Init(void);
6879 extern void R_Sky_Init(void);
6880 extern void GL_Surf_Init(void);
6881 extern void R_Particles_Init(void);
6882 extern void R_Explosion_Init(void);
6883 extern void gl_backend_init(void);
6884 extern void Sbar_Init(void);
6885 extern void R_LightningBeams_Init(void);
6886 extern void Mod_RenderInit(void);
6887 extern void Font_Init(void);
6888
6889 void Render_Init(void)
6890 {
6891         gl_backend_init();
6892         R_Textures_Init();
6893         GL_Main_Init();
6894         Font_Init();
6895         GL_Draw_Init();
6896         R_Shadow_Init();
6897         R_Sky_Init();
6898         GL_Surf_Init();
6899         Sbar_Init();
6900         R_Particles_Init();
6901         R_Explosion_Init();
6902         R_LightningBeams_Init();
6903         Mod_RenderInit();
6904 }
6905
6906 /*
6907 ===============
6908 GL_Init
6909 ===============
6910 */
6911 extern char *ENGINE_EXTENSIONS;
6912 void GL_Init (void)
6913 {
6914         gl_renderer = (const char *)qglGetString(GL_RENDERER);
6915         gl_vendor = (const char *)qglGetString(GL_VENDOR);
6916         gl_version = (const char *)qglGetString(GL_VERSION);
6917         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6918
6919         if (!gl_extensions)
6920                 gl_extensions = "";
6921         if (!gl_platformextensions)
6922                 gl_platformextensions = "";
6923
6924         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6925         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6926         Con_Printf("GL_VERSION: %s\n", gl_version);
6927         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6928         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6929
6930         VID_CheckExtensions();
6931
6932         // LordHavoc: report supported extensions
6933         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6934
6935         // clear to black (loading plaque will be seen over this)
6936         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6937 }
6938
6939 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6940 {
6941         int i;
6942         mplane_t *p;
6943         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6944         {
6945                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6946                 if (i == 4)
6947                         continue;
6948                 p = r_refdef.view.frustum + i;
6949                 switch(p->signbits)
6950                 {
6951                 default:
6952                 case 0:
6953                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6954                                 return true;
6955                         break;
6956                 case 1:
6957                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6958                                 return true;
6959                         break;
6960                 case 2:
6961                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6962                                 return true;
6963                         break;
6964                 case 3:
6965                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6966                                 return true;
6967                         break;
6968                 case 4:
6969                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6970                                 return true;
6971                         break;
6972                 case 5:
6973                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6974                                 return true;
6975                         break;
6976                 case 6:
6977                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6978                                 return true;
6979                         break;
6980                 case 7:
6981                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6982                                 return true;
6983                         break;
6984                 }
6985         }
6986         return false;
6987 }
6988
6989 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6990 {
6991         int i;
6992         const mplane_t *p;
6993         for (i = 0;i < numplanes;i++)
6994         {
6995                 p = planes + i;
6996                 switch(p->signbits)
6997                 {
6998                 default:
6999                 case 0:
7000                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7001                                 return true;
7002                         break;
7003                 case 1:
7004                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7005                                 return true;
7006                         break;
7007                 case 2:
7008                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7009                                 return true;
7010                         break;
7011                 case 3:
7012                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7013                                 return true;
7014                         break;
7015                 case 4:
7016                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7017                                 return true;
7018                         break;
7019                 case 5:
7020                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7021                                 return true;
7022                         break;
7023                 case 6:
7024                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7025                                 return true;
7026                         break;
7027                 case 7:
7028                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7029                                 return true;
7030                         break;
7031                 }
7032         }
7033         return false;
7034 }
7035
7036 //==================================================================================
7037
7038 // LordHavoc: this stores temporary data used within the same frame
7039
7040 typedef struct r_framedata_mem_s
7041 {
7042         struct r_framedata_mem_s *purge; // older mem block to free on next frame
7043         size_t size; // how much usable space
7044         size_t current; // how much space in use
7045         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7046         size_t wantedsize; // how much space was allocated
7047         unsigned char *data; // start of real data (16byte aligned)
7048 }
7049 r_framedata_mem_t;
7050
7051 static r_framedata_mem_t *r_framedata_mem;
7052
7053 void R_FrameData_Reset(void)
7054 {
7055         while (r_framedata_mem)
7056         {
7057                 r_framedata_mem_t *next = r_framedata_mem->purge;
7058                 Mem_Free(r_framedata_mem);
7059                 r_framedata_mem = next;
7060         }
7061 }
7062
7063 void R_FrameData_Resize(void)
7064 {
7065         size_t wantedsize;
7066         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7067         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7068         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7069         {
7070                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
7071                 newmem->wantedsize = wantedsize;
7072                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7073                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7074                 newmem->current = 0;
7075                 newmem->mark = 0;
7076                 newmem->purge = r_framedata_mem;
7077                 r_framedata_mem = newmem;
7078         }
7079 }
7080
7081 void R_FrameData_NewFrame(void)
7082 {
7083         R_FrameData_Resize();
7084         if (!r_framedata_mem)
7085                 return;
7086         // if we ran out of space on the last frame, free the old memory now
7087         while (r_framedata_mem->purge)
7088         {
7089                 // repeatedly remove the second item in the list, leaving only head
7090                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7091                 Mem_Free(r_framedata_mem->purge);
7092                 r_framedata_mem->purge = next;
7093         }
7094         // reset the current mem pointer
7095         r_framedata_mem->current = 0;
7096         r_framedata_mem->mark = 0;
7097 }
7098
7099 void *R_FrameData_Alloc(size_t size)
7100 {
7101         void *data;
7102
7103         // align to 16 byte boundary - the data pointer is already aligned, so we
7104         // only need to ensure the size of every allocation is also aligned
7105         size = (size + 15) & ~15;
7106
7107         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
7108         {
7109                 // emergency - we ran out of space, allocate more memory
7110                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
7111                 R_FrameData_Resize();
7112         }
7113
7114         data = r_framedata_mem->data + r_framedata_mem->current;
7115         r_framedata_mem->current += size;
7116
7117         // count the usage for stats
7118         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
7119         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
7120
7121         return (void *)data;
7122 }
7123
7124 void *R_FrameData_Store(size_t size, void *data)
7125 {
7126         void *d = R_FrameData_Alloc(size);
7127         if (d && data)
7128                 memcpy(d, data, size);
7129         return d;
7130 }
7131
7132 void R_FrameData_SetMark(void)
7133 {
7134         if (!r_framedata_mem)
7135                 return;
7136         r_framedata_mem->mark = r_framedata_mem->current;
7137 }
7138
7139 void R_FrameData_ReturnToMark(void)
7140 {
7141         if (!r_framedata_mem)
7142                 return;
7143         r_framedata_mem->current = r_framedata_mem->mark;
7144 }
7145
7146 //==================================================================================
7147
7148 // LordHavoc: animcache originally written by Echon, rewritten since then
7149
7150 /**
7151  * Animation cache prevents re-generating mesh data for an animated model
7152  * multiple times in one frame for lighting, shadowing, reflections, etc.
7153  */
7154
7155 void R_AnimCache_Free(void)
7156 {
7157 }
7158
7159 void R_AnimCache_ClearCache(void)
7160 {
7161         int i;
7162         entity_render_t *ent;
7163
7164         for (i = 0;i < r_refdef.scene.numentities;i++)
7165         {
7166                 ent = r_refdef.scene.entities[i];
7167                 ent->animcache_vertex3f = NULL;
7168                 ent->animcache_normal3f = NULL;
7169                 ent->animcache_svector3f = NULL;
7170                 ent->animcache_tvector3f = NULL;
7171                 ent->animcache_vertexmesh = NULL;
7172                 ent->animcache_vertex3fbuffer = NULL;
7173                 ent->animcache_vertexmeshbuffer = NULL;
7174         }
7175 }
7176
7177 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7178 {
7179         int i;
7180
7181         // check if we need the meshbuffers
7182         if (!vid.useinterleavedarrays)
7183                 return;
7184
7185         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7186                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7187         // TODO: upload vertex3f buffer?
7188         if (ent->animcache_vertexmesh)
7189         {
7190                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7191                 for (i = 0;i < numvertices;i++)
7192                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7193                 if (ent->animcache_svector3f)
7194                         for (i = 0;i < numvertices;i++)
7195                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7196                 if (ent->animcache_tvector3f)
7197                         for (i = 0;i < numvertices;i++)
7198                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7199                 if (ent->animcache_normal3f)
7200                         for (i = 0;i < numvertices;i++)
7201                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7202                 // TODO: upload vertexmeshbuffer?
7203         }
7204 }
7205
7206 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7207 {
7208         dp_model_t *model = ent->model;
7209         int numvertices;
7210         // see if it's already cached this frame
7211         if (ent->animcache_vertex3f)
7212         {
7213                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7214                 if (wantnormals || wanttangents)
7215                 {
7216                         if (ent->animcache_normal3f)
7217                                 wantnormals = false;
7218                         if (ent->animcache_svector3f)
7219                                 wanttangents = false;
7220                         if (wantnormals || wanttangents)
7221                         {
7222                                 numvertices = model->surfmesh.num_vertices;
7223                                 if (wantnormals)
7224                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7225                                 if (wanttangents)
7226                                 {
7227                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7228                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7229                                 }
7230                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7231                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7232                         }
7233                 }
7234         }
7235         else
7236         {
7237                 // see if this ent is worth caching
7238                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7239                         return false;
7240                 // get some memory for this entity and generate mesh data
7241                 numvertices = model->surfmesh.num_vertices;
7242                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7243                 if (wantnormals)
7244                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7245                 if (wanttangents)
7246                 {
7247                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7248                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7249                 }
7250                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7251                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7252         }
7253         return true;
7254 }
7255
7256 void R_AnimCache_CacheVisibleEntities(void)
7257 {
7258         int i;
7259         qboolean wantnormals = true;
7260         qboolean wanttangents = !r_showsurfaces.integer;
7261
7262         switch(vid.renderpath)
7263         {
7264         case RENDERPATH_GL20:
7265         case RENDERPATH_D3D9:
7266         case RENDERPATH_D3D10:
7267         case RENDERPATH_D3D11:
7268         case RENDERPATH_GLES2:
7269                 break;
7270         case RENDERPATH_GL13:
7271         case RENDERPATH_GL11:
7272                 wanttangents = false;
7273                 break;
7274         case RENDERPATH_SOFT:
7275                 break;
7276         }
7277
7278         if (r_shownormals.integer)
7279                 wanttangents = wantnormals = true;
7280
7281         // TODO: thread this
7282         // NOTE: R_PrepareRTLights() also caches entities
7283
7284         for (i = 0;i < r_refdef.scene.numentities;i++)
7285                 if (r_refdef.viewcache.entityvisible[i])
7286                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7287 }
7288
7289 //==================================================================================
7290
7291 static void R_View_UpdateEntityLighting (void)
7292 {
7293         int i;
7294         entity_render_t *ent;
7295         vec3_t tempdiffusenormal, avg;
7296         vec_t f, fa, fd, fdd;
7297         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7298
7299         for (i = 0;i < r_refdef.scene.numentities;i++)
7300         {
7301                 ent = r_refdef.scene.entities[i];
7302
7303                 // skip unseen models
7304                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7305                         continue;
7306
7307                 // skip bsp models
7308                 if (ent->model && ent->model->brush.num_leafs)
7309                 {
7310                         // TODO: use modellight for r_ambient settings on world?
7311                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7312                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7313                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7314                         continue;
7315                 }
7316
7317                 // fetch the lighting from the worldmodel data
7318                 VectorClear(ent->modellight_ambient);
7319                 VectorClear(ent->modellight_diffuse);
7320                 VectorClear(tempdiffusenormal);
7321                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7322                 {
7323                         vec3_t org;
7324                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7325
7326                         // complete lightning for lit sprites
7327                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7328                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7329                         {
7330                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7331                                         org[2] = org[2] + r_overheadsprites_pushback.value;
7332                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7333                         }
7334                         else
7335                                 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7336
7337                         if(ent->flags & RENDER_EQUALIZE)
7338                         {
7339                                 // first fix up ambient lighting...
7340                                 if(r_equalize_entities_minambient.value > 0)
7341                                 {
7342                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7343                                         if(fd > 0)
7344                                         {
7345                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7346                                                 if(fa < r_equalize_entities_minambient.value * fd)
7347                                                 {
7348                                                         // solve:
7349                                                         //   fa'/fd' = minambient
7350                                                         //   fa'+0.25*fd' = fa+0.25*fd
7351                                                         //   ...
7352                                                         //   fa' = fd' * minambient
7353                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7354                                                         //   ...
7355                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7356                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7357                                                         //   ...
7358                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7359                                                         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
7360                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7361                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7362                                                 }
7363                                         }
7364                                 }
7365
7366                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7367                                 {
7368                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
7369                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7370                                         f = fa + 0.25 * fd;
7371                                         if(f > 0)
7372                                         {
7373                                                 // adjust brightness and saturation to target
7374                                                 avg[0] = avg[1] = avg[2] = fa / f;
7375                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
7376                                                 avg[0] = avg[1] = avg[2] = fd / f;
7377                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
7378                                         }
7379                                 }
7380                         }
7381                 }
7382                 else // highly rare
7383                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7384
7385                 // move the light direction into modelspace coordinates for lighting code
7386                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7387                 if(VectorLength2(ent->modellight_lightdir) == 0)
7388                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7389                 VectorNormalize(ent->modellight_lightdir);
7390         }
7391 }
7392
7393 #define MAX_LINEOFSIGHTTRACES 64
7394
7395 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7396 {
7397         int i;
7398         vec3_t boxmins, boxmaxs;
7399         vec3_t start;
7400         vec3_t end;
7401         dp_model_t *model = r_refdef.scene.worldmodel;
7402
7403         if (!model || !model->brush.TraceLineOfSight)
7404                 return true;
7405
7406         // expand the box a little
7407         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7408         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7409         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7410         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7411         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7412         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7413
7414         // return true if eye is inside enlarged box
7415         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7416                 return true;
7417
7418         // try center
7419         VectorCopy(eye, start);
7420         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7421         if (model->brush.TraceLineOfSight(model, start, end))
7422                 return true;
7423
7424         // try various random positions
7425         for (i = 0;i < numsamples;i++)
7426         {
7427                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7428                 if (model->brush.TraceLineOfSight(model, start, end))
7429                         return true;
7430         }
7431
7432         return false;
7433 }
7434
7435
7436 static void R_View_UpdateEntityVisible (void)
7437 {
7438         int i;
7439         int renderimask;
7440         int samples;
7441         entity_render_t *ent;
7442
7443         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7444                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7445                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
7446                 :                                                          RENDER_EXTERIORMODEL;
7447         if (!r_drawviewmodel.integer)
7448                 renderimask |= RENDER_VIEWMODEL;
7449         if (!r_drawexteriormodel.integer)
7450                 renderimask |= RENDER_EXTERIORMODEL;
7451         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7452         {
7453                 // worldmodel can check visibility
7454                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7455                 for (i = 0;i < r_refdef.scene.numentities;i++)
7456                 {
7457                         ent = r_refdef.scene.entities[i];
7458                         if (!(ent->flags & renderimask))
7459                         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)))
7460                         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))
7461                                 r_refdef.viewcache.entityvisible[i] = true;
7462                 }
7463                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7464                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7465                 {
7466                         for (i = 0;i < r_refdef.scene.numentities;i++)
7467                         {
7468                                 ent = r_refdef.scene.entities[i];
7469                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7470                                 {
7471                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7472                                         if (samples < 0)
7473                                                 continue; // temp entities do pvs only
7474                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7475                                                 ent->last_trace_visibility = realtime;
7476                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7477                                                 r_refdef.viewcache.entityvisible[i] = 0;
7478                                 }
7479                         }
7480                 }
7481         }
7482         else
7483         {
7484                 // no worldmodel or it can't check visibility
7485                 for (i = 0;i < r_refdef.scene.numentities;i++)
7486                 {
7487                         ent = r_refdef.scene.entities[i];
7488                         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));
7489                 }
7490         }
7491 }
7492
7493 /// only used if skyrendermasked, and normally returns false
7494 int R_DrawBrushModelsSky (void)
7495 {
7496         int i, sky;
7497         entity_render_t *ent;
7498
7499         sky = false;
7500         for (i = 0;i < r_refdef.scene.numentities;i++)
7501         {
7502                 if (!r_refdef.viewcache.entityvisible[i])
7503                         continue;
7504                 ent = r_refdef.scene.entities[i];
7505                 if (!ent->model || !ent->model->DrawSky)
7506                         continue;
7507                 ent->model->DrawSky(ent);
7508                 sky = true;
7509         }
7510         return sky;
7511 }
7512
7513 static void R_DrawNoModel(entity_render_t *ent);
7514 static void R_DrawModels(void)
7515 {
7516         int i;
7517         entity_render_t *ent;
7518
7519         for (i = 0;i < r_refdef.scene.numentities;i++)
7520         {
7521                 if (!r_refdef.viewcache.entityvisible[i])
7522                         continue;
7523                 ent = r_refdef.scene.entities[i];
7524                 r_refdef.stats.entities++;
7525                 if (ent->model && ent->model->Draw != NULL)
7526                         ent->model->Draw(ent);
7527                 else
7528                         R_DrawNoModel(ent);
7529         }
7530 }
7531
7532 static void R_DrawModelsDepth(void)
7533 {
7534         int i;
7535         entity_render_t *ent;
7536
7537         for (i = 0;i < r_refdef.scene.numentities;i++)
7538         {
7539                 if (!r_refdef.viewcache.entityvisible[i])
7540                         continue;
7541                 ent = r_refdef.scene.entities[i];
7542                 if (ent->model && ent->model->DrawDepth != NULL)
7543                         ent->model->DrawDepth(ent);
7544         }
7545 }
7546
7547 static void R_DrawModelsDebug(void)
7548 {
7549         int i;
7550         entity_render_t *ent;
7551
7552         for (i = 0;i < r_refdef.scene.numentities;i++)
7553         {
7554                 if (!r_refdef.viewcache.entityvisible[i])
7555                         continue;
7556                 ent = r_refdef.scene.entities[i];
7557                 if (ent->model && ent->model->DrawDebug != NULL)
7558                         ent->model->DrawDebug(ent);
7559         }
7560 }
7561
7562 static void R_DrawModelsAddWaterPlanes(void)
7563 {
7564         int i;
7565         entity_render_t *ent;
7566
7567         for (i = 0;i < r_refdef.scene.numentities;i++)
7568         {
7569                 if (!r_refdef.viewcache.entityvisible[i])
7570                         continue;
7571                 ent = r_refdef.scene.entities[i];
7572                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7573                         ent->model->DrawAddWaterPlanes(ent);
7574         }
7575 }
7576
7577 static void R_View_SetFrustum(const int *scissor)
7578 {
7579         int i;
7580         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
7581         vec3_t forward, left, up, origin, v;
7582
7583         if(scissor)
7584         {
7585                 // flipped x coordinates (because x points left here)
7586                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7587                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7588
7589                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
7590                 switch(vid.renderpath)
7591                 {
7592                         case RENDERPATH_D3D9:
7593                         case RENDERPATH_D3D10:
7594                         case RENDERPATH_D3D11:
7595                         case RENDERPATH_SOFT:
7596                                 // non-flipped y coordinates
7597                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7598                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7599                                 break;
7600                         case RENDERPATH_GL11:
7601                         case RENDERPATH_GL13:
7602                         case RENDERPATH_GL20:
7603                         case RENDERPATH_GLES2:
7604                                 // non-flipped y coordinates
7605                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7606                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7607                                 break;
7608                 }
7609         }
7610
7611         // we can't trust r_refdef.view.forward and friends in reflected scenes
7612         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7613
7614 #if 0
7615         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7616         r_refdef.view.frustum[0].normal[1] = 0 - 0;
7617         r_refdef.view.frustum[0].normal[2] = -1 - 0;
7618         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7619         r_refdef.view.frustum[1].normal[1] = 0 + 0;
7620         r_refdef.view.frustum[1].normal[2] = -1 + 0;
7621         r_refdef.view.frustum[2].normal[0] = 0 - 0;
7622         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7623         r_refdef.view.frustum[2].normal[2] = -1 - 0;
7624         r_refdef.view.frustum[3].normal[0] = 0 + 0;
7625         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7626         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7627 #endif
7628
7629 #if 0
7630         zNear = r_refdef.nearclip;
7631         nudge = 1.0 - 1.0 / (1<<23);
7632         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7633         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7634         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7635         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7636         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7637         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7638         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7639         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7640 #endif
7641
7642
7643
7644 #if 0
7645         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7646         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7647         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7648         r_refdef.view.frustum[0].dist = m[15] - m[12];
7649
7650         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7651         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7652         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7653         r_refdef.view.frustum[1].dist = m[15] + m[12];
7654
7655         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7656         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7657         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7658         r_refdef.view.frustum[2].dist = m[15] - m[13];
7659
7660         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7661         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7662         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7663         r_refdef.view.frustum[3].dist = m[15] + m[13];
7664
7665         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7666         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7667         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7668         r_refdef.view.frustum[4].dist = m[15] - m[14];
7669
7670         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7671         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7672         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7673         r_refdef.view.frustum[5].dist = m[15] + m[14];
7674 #endif
7675
7676         if (r_refdef.view.useperspective)
7677         {
7678                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7679                 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]);
7680                 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]);
7681                 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]);
7682                 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]);
7683
7684                 // then the normals from the corners relative to origin
7685                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
7686                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
7687                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
7688                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
7689
7690                 // in a NORMAL view, forward cross left == up
7691                 // in a REFLECTED view, forward cross left == down
7692                 // so our cross products above need to be adjusted for a left handed coordinate system
7693                 CrossProduct(forward, left, v);
7694                 if(DotProduct(v, up) < 0)
7695                 {
7696                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
7697                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
7698                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
7699                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
7700                 }
7701
7702                 // Leaving those out was a mistake, those were in the old code, and they
7703                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7704                 // I couldn't reproduce it after adding those normalizations. --blub
7705                 VectorNormalize(r_refdef.view.frustum[0].normal);
7706                 VectorNormalize(r_refdef.view.frustum[1].normal);
7707                 VectorNormalize(r_refdef.view.frustum[2].normal);
7708                 VectorNormalize(r_refdef.view.frustum[3].normal);
7709
7710                 // make the corners absolute
7711                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
7712                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
7713                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
7714                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
7715
7716                 // one more normal
7717                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7718
7719                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7720                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7721                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7722                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7723                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7724         }
7725         else
7726         {
7727                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7728                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7729                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7730                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7731                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7732                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7733                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7734                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7735                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7736                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7737         }
7738         r_refdef.view.numfrustumplanes = 5;
7739
7740         if (r_refdef.view.useclipplane)
7741         {
7742                 r_refdef.view.numfrustumplanes = 6;
7743                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7744         }
7745
7746         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7747                 PlaneClassify(r_refdef.view.frustum + i);
7748
7749         // LordHavoc: note to all quake engine coders, Quake had a special case
7750         // for 90 degrees which assumed a square view (wrong), so I removed it,
7751         // Quake2 has it disabled as well.
7752
7753         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7754         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7755         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7756         //PlaneClassify(&frustum[0]);
7757
7758         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7759         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7760         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7761         //PlaneClassify(&frustum[1]);
7762
7763         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7764         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7765         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7766         //PlaneClassify(&frustum[2]);
7767
7768         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7769         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7770         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7771         //PlaneClassify(&frustum[3]);
7772
7773         // nearclip plane
7774         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7775         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7776         //PlaneClassify(&frustum[4]);
7777 }
7778
7779 void R_View_UpdateWithScissor(const int *myscissor)
7780 {
7781         R_Main_ResizeViewCache();
7782         R_View_SetFrustum(myscissor);
7783         R_View_WorldVisibility(r_refdef.view.useclipplane);
7784         R_View_UpdateEntityVisible();
7785         R_View_UpdateEntityLighting();
7786 }
7787
7788 void R_View_Update(void)
7789 {
7790         R_Main_ResizeViewCache();
7791         R_View_SetFrustum(NULL);
7792         R_View_WorldVisibility(r_refdef.view.useclipplane);
7793         R_View_UpdateEntityVisible();
7794         R_View_UpdateEntityLighting();
7795 }
7796
7797 void R_SetupView(qboolean allowwaterclippingplane)
7798 {
7799         const float *customclipplane = NULL;
7800         float plane[4];
7801         if (r_refdef.view.useclipplane && allowwaterclippingplane)
7802         {
7803                 // LordHavoc: couldn't figure out how to make this approach the
7804                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7805                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7806                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7807                         dist = r_refdef.view.clipplane.dist;
7808                 plane[0] = r_refdef.view.clipplane.normal[0];
7809                 plane[1] = r_refdef.view.clipplane.normal[1];
7810                 plane[2] = r_refdef.view.clipplane.normal[2];
7811                 plane[3] = dist;
7812                 customclipplane = plane;
7813         }
7814
7815         if (!r_refdef.view.useperspective)
7816                 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);
7817         else if (vid.stencil && r_useinfinitefarclip.integer)
7818                 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);
7819         else
7820                 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);
7821         R_SetViewport(&r_refdef.view.viewport);
7822 }
7823
7824 void R_EntityMatrix(const matrix4x4_t *matrix)
7825 {
7826         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7827         {
7828                 gl_modelmatrixchanged = false;
7829                 gl_modelmatrix = *matrix;
7830                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7831                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7832                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7833                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7834                 CHECKGLERROR
7835                 switch(vid.renderpath)
7836                 {
7837                 case RENDERPATH_D3D9:
7838 #ifdef SUPPORTD3D
7839                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
7840                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
7841 #endif
7842                         break;
7843                 case RENDERPATH_D3D10:
7844                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
7845                         break;
7846                 case RENDERPATH_D3D11:
7847                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
7848                         break;
7849                 case RENDERPATH_GL13:
7850                 case RENDERPATH_GL11:
7851                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7852                         break;
7853                 case RENDERPATH_SOFT:
7854                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
7855                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
7856                         break;
7857                 case RENDERPATH_GL20:
7858                 case RENDERPATH_GLES2:
7859                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7860                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7861                         break;
7862                 }
7863         }
7864 }
7865
7866 void R_ResetViewRendering2D(void)
7867 {
7868         r_viewport_t viewport;
7869         DrawQ_Finish();
7870
7871         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7872         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);
7873         R_SetViewport(&viewport);
7874         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7875         GL_Color(1, 1, 1, 1);
7876         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7877         GL_BlendFunc(GL_ONE, GL_ZERO);
7878         GL_ScissorTest(false);
7879         GL_DepthMask(false);
7880         GL_DepthRange(0, 1);
7881         GL_DepthTest(false);
7882         GL_DepthFunc(GL_LEQUAL);
7883         R_EntityMatrix(&identitymatrix);
7884         R_Mesh_ResetTextureState();
7885         GL_PolygonOffset(0, 0);
7886         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
7887         switch(vid.renderpath)
7888         {
7889         case RENDERPATH_GL11:
7890         case RENDERPATH_GL13:
7891         case RENDERPATH_GL20:
7892         case RENDERPATH_GLES2:
7893                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7894                 break;
7895         case RENDERPATH_D3D9:
7896         case RENDERPATH_D3D10:
7897         case RENDERPATH_D3D11:
7898         case RENDERPATH_SOFT:
7899                 break;
7900         }
7901         GL_CullFace(GL_NONE);
7902 }
7903
7904 void R_ResetViewRendering3D(void)
7905 {
7906         DrawQ_Finish();
7907
7908         R_SetupView(true);
7909         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7910         GL_Color(1, 1, 1, 1);
7911         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7912         GL_BlendFunc(GL_ONE, GL_ZERO);
7913         GL_ScissorTest(true);
7914         GL_DepthMask(true);
7915         GL_DepthRange(0, 1);
7916         GL_DepthTest(true);
7917         GL_DepthFunc(GL_LEQUAL);
7918         R_EntityMatrix(&identitymatrix);
7919         R_Mesh_ResetTextureState();
7920         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7921         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
7922         switch(vid.renderpath)
7923         {
7924         case RENDERPATH_GL11:
7925         case RENDERPATH_GL13:
7926         case RENDERPATH_GL20:
7927         case RENDERPATH_GLES2:
7928                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7929                 break;
7930         case RENDERPATH_D3D9:
7931         case RENDERPATH_D3D10:
7932         case RENDERPATH_D3D11:
7933         case RENDERPATH_SOFT:
7934                 break;
7935         }
7936         GL_CullFace(r_refdef.view.cullface_back);
7937 }
7938
7939 /*
7940 ================
7941 R_RenderView_UpdateViewVectors
7942 ================
7943 */
7944 static void R_RenderView_UpdateViewVectors(void)
7945 {
7946         // break apart the view matrix into vectors for various purposes
7947         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7948         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7949         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7950         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7951         // make an inverted copy of the view matrix for tracking sprites
7952         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7953 }
7954
7955 void R_RenderScene(void);
7956 void R_RenderWaterPlanes(void);
7957
7958 static void R_Water_StartFrame(void)
7959 {
7960         int i;
7961         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
7962         r_waterstate_waterplane_t *p;
7963
7964         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7965                 return;
7966
7967         switch(vid.renderpath)
7968         {
7969         case RENDERPATH_GL20:
7970         case RENDERPATH_D3D9:
7971         case RENDERPATH_D3D10:
7972         case RENDERPATH_D3D11:
7973         case RENDERPATH_SOFT:
7974         case RENDERPATH_GLES2:
7975                 break;
7976         case RENDERPATH_GL13:
7977         case RENDERPATH_GL11:
7978                 return;
7979         }
7980
7981         // set waterwidth and waterheight to the water resolution that will be
7982         // used (often less than the screen resolution for faster rendering)
7983         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7984         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7985
7986         // calculate desired texture sizes
7987         // can't use water if the card does not support the texture size
7988         if (!r_water.integer || r_showsurfaces.integer)
7989                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
7990         else if (vid.support.arb_texture_non_power_of_two)
7991         {
7992                 texturewidth = waterwidth;
7993                 textureheight = waterheight;
7994                 camerawidth = waterwidth;
7995                 cameraheight = waterheight;
7996         }
7997         else
7998         {
7999                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8000                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8001                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8002                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8003         }
8004
8005         // allocate textures as needed
8006         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8007         {
8008                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8009                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8010                 {
8011                         if (p->texture_refraction)
8012                                 R_FreeTexture(p->texture_refraction);
8013                         p->texture_refraction = NULL;
8014                         if (p->texture_reflection)
8015                                 R_FreeTexture(p->texture_reflection);
8016                         p->texture_reflection = NULL;
8017                         if (p->texture_camera)
8018                                 R_FreeTexture(p->texture_camera);
8019                         p->texture_camera = NULL;
8020                 }
8021                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8022                 r_waterstate.texturewidth = texturewidth;
8023                 r_waterstate.textureheight = textureheight;
8024                 r_waterstate.camerawidth = camerawidth;
8025                 r_waterstate.cameraheight = cameraheight;
8026         }
8027
8028         if (r_waterstate.texturewidth)
8029         {
8030                 r_waterstate.enabled = true;
8031
8032                 // when doing a reduced render (HDR) we want to use a smaller area
8033                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8034                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8035
8036                 // set up variables that will be used in shader setup
8037                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8038                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8039                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8040                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8041         }
8042
8043         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8044         r_waterstate.numwaterplanes = 0;
8045 }
8046
8047 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8048 {
8049         int triangleindex, planeindex;
8050         const int *e;
8051         vec3_t vert[3];
8052         vec3_t normal;
8053         vec3_t center;
8054         mplane_t plane;
8055         r_waterstate_waterplane_t *p;
8056         texture_t *t = R_GetCurrentTexture(surface->texture);
8057
8058         // just use the first triangle with a valid normal for any decisions
8059         VectorClear(normal);
8060         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8061         {
8062                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8063                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8064                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8065                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8066                 if (VectorLength2(normal) >= 0.001)
8067                         break;
8068         }
8069
8070         VectorCopy(normal, plane.normal);
8071         VectorNormalize(plane.normal);
8072         plane.dist = DotProduct(vert[0], plane.normal);
8073         PlaneClassify(&plane);
8074         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8075         {
8076                 // skip backfaces (except if nocullface is set)
8077                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8078                         return;
8079                 VectorNegate(plane.normal, plane.normal);
8080                 plane.dist *= -1;
8081                 PlaneClassify(&plane);
8082         }
8083
8084
8085         // find a matching plane if there is one
8086         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8087                 if(p->camera_entity == t->camera_entity)
8088                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8089                                 break;
8090         if (planeindex >= r_waterstate.maxwaterplanes)
8091                 return; // nothing we can do, out of planes
8092
8093         // if this triangle does not fit any known plane rendered this frame, add one
8094         if (planeindex >= r_waterstate.numwaterplanes)
8095         {
8096                 // store the new plane
8097                 r_waterstate.numwaterplanes++;
8098                 p->plane = plane;
8099                 // clear materialflags and pvs
8100                 p->materialflags = 0;
8101                 p->pvsvalid = false;
8102                 p->camera_entity = t->camera_entity;
8103                 VectorCopy(surface->mins, p->mins);
8104                 VectorCopy(surface->maxs, p->maxs);
8105         }
8106         else
8107         {
8108                 // merge mins/maxs
8109                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8110                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8111                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8112                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8113                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8114                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8115         }
8116         // merge this surface's materialflags into the waterplane
8117         p->materialflags |= t->currentmaterialflags;
8118         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8119         {
8120                 // merge this surface's PVS into the waterplane
8121                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8122                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8123                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8124                 {
8125                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8126                         p->pvsvalid = true;
8127                 }
8128         }
8129 }
8130
8131 static void R_Water_ProcessPlanes(void)
8132 {
8133         int myscissor[4];
8134         r_refdef_view_t originalview;
8135         r_refdef_view_t myview;
8136         int planeindex;
8137         r_waterstate_waterplane_t *p;
8138         vec3_t visorigin;
8139
8140         originalview = r_refdef.view;
8141
8142         // make sure enough textures are allocated
8143         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8144         {
8145                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8146                 {
8147                         if (!p->texture_refraction)
8148                                 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);
8149                         if (!p->texture_refraction)
8150                                 goto error;
8151                 }
8152                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8153                 {
8154                         if (!p->texture_camera)
8155                                 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);
8156                         if (!p->texture_camera)
8157                                 goto error;
8158                 }
8159
8160                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8161                 {
8162                         if (!p->texture_reflection)
8163                                 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);
8164                         if (!p->texture_reflection)
8165                                 goto error;
8166                 }
8167         }
8168
8169         // render views
8170         r_refdef.view = originalview;
8171         r_refdef.view.showdebug = false;
8172         r_refdef.view.width = r_waterstate.waterwidth;
8173         r_refdef.view.height = r_waterstate.waterheight;
8174         r_refdef.view.useclipplane = true;
8175         myview = r_refdef.view;
8176         r_waterstate.renderingscene = true;
8177         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8178         {
8179                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8180                 {
8181                         r_refdef.view = myview;
8182                         if(r_water_scissormode.integer)
8183                         {
8184                                 R_SetupView(true);
8185                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8186                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8187                         }
8188
8189                         // render reflected scene and copy into texture
8190                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8191                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8192                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8193                         r_refdef.view.clipplane = p->plane;
8194
8195                         // reverse the cullface settings for this render
8196                         r_refdef.view.cullface_front = GL_FRONT;
8197                         r_refdef.view.cullface_back = GL_BACK;
8198                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8199                         {
8200                                 r_refdef.view.usecustompvs = true;
8201                                 if (p->pvsvalid)
8202                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8203                                 else
8204                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8205                         }
8206
8207                         R_ResetViewRendering3D();
8208                         R_ClearScreen(r_refdef.fogenabled);
8209                         if(r_water_scissormode.integer & 2)
8210                                 R_View_UpdateWithScissor(myscissor);
8211                         else
8212                                 R_View_Update();
8213                         if(r_water_scissormode.integer & 1)
8214                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8215                         R_RenderScene();
8216
8217                         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);
8218                 }
8219
8220                 // render the normal view scene and copy into texture
8221                 // (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)
8222                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8223                 {
8224                         r_refdef.view = myview;
8225                         if(r_water_scissormode.integer)
8226                         {
8227                                 R_SetupView(true);
8228                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8229                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8230                         }
8231
8232                         r_waterstate.renderingrefraction = true;
8233
8234                         r_refdef.view.clipplane = p->plane;
8235                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8236                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8237
8238                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8239                         {
8240                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8241                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8242                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8243                                 R_RenderView_UpdateViewVectors();
8244                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8245                                 {
8246                                         r_refdef.view.usecustompvs = true;
8247                                         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);
8248                                 }
8249                         }
8250
8251                         PlaneClassify(&r_refdef.view.clipplane);
8252
8253                         R_ResetViewRendering3D();
8254                         R_ClearScreen(r_refdef.fogenabled);
8255                         if(r_water_scissormode.integer & 2)
8256                                 R_View_UpdateWithScissor(myscissor);
8257                         else
8258                                 R_View_Update();
8259                         if(r_water_scissormode.integer & 1)
8260                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8261                         R_RenderScene();
8262
8263                         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);
8264                         r_waterstate.renderingrefraction = false;
8265                 }
8266                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8267                 {
8268                         r_refdef.view = myview;
8269
8270                         r_refdef.view.clipplane = p->plane;
8271                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8272                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8273
8274                         r_refdef.view.width = r_waterstate.camerawidth;
8275                         r_refdef.view.height = r_waterstate.cameraheight;
8276                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8277                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8278
8279                         if(p->camera_entity)
8280                         {
8281                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8282                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8283                         }
8284
8285                         // note: all of the view is used for displaying... so
8286                         // there is no use in scissoring
8287
8288                         // reverse the cullface settings for this render
8289                         r_refdef.view.cullface_front = GL_FRONT;
8290                         r_refdef.view.cullface_back = GL_BACK;
8291                         // also reverse the view matrix
8292                         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
8293                         R_RenderView_UpdateViewVectors();
8294                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8295                         {
8296                                 r_refdef.view.usecustompvs = true;
8297                                 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);
8298                         }
8299                         
8300                         // camera needs no clipplane
8301                         r_refdef.view.useclipplane = false;
8302
8303                         PlaneClassify(&r_refdef.view.clipplane);
8304
8305                         R_ResetViewRendering3D();
8306                         R_ClearScreen(r_refdef.fogenabled);
8307                         R_View_Update();
8308                         R_RenderScene();
8309
8310                         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);
8311                         r_waterstate.renderingrefraction = false;
8312                 }
8313
8314         }
8315         r_waterstate.renderingscene = false;
8316         r_refdef.view = originalview;
8317         R_ResetViewRendering3D();
8318         R_ClearScreen(r_refdef.fogenabled);
8319         R_View_Update();
8320         return;
8321 error:
8322         r_refdef.view = originalview;
8323         r_waterstate.renderingscene = false;
8324         Cvar_SetValueQuick(&r_water, 0);
8325         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8326         return;
8327 }
8328
8329 void R_Bloom_StartFrame(void)
8330 {
8331         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8332
8333         switch(vid.renderpath)
8334         {
8335         case RENDERPATH_GL20:
8336         case RENDERPATH_D3D9:
8337         case RENDERPATH_D3D10:
8338         case RENDERPATH_D3D11:
8339         case RENDERPATH_SOFT:
8340         case RENDERPATH_GLES2:
8341                 break;
8342         case RENDERPATH_GL13:
8343         case RENDERPATH_GL11:
8344                 return;
8345         }
8346
8347         // set bloomwidth and bloomheight to the bloom resolution that will be
8348         // used (often less than the screen resolution for faster rendering)
8349         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8350         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8351         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8352         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8353         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8354
8355         // calculate desired texture sizes
8356         if (vid.support.arb_texture_non_power_of_two)
8357         {
8358                 screentexturewidth = r_refdef.view.width;
8359                 screentextureheight = r_refdef.view.height;
8360                 bloomtexturewidth = r_bloomstate.bloomwidth;
8361                 bloomtextureheight = r_bloomstate.bloomheight;
8362         }
8363         else
8364         {
8365                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8366                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8367                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8368                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8369         }
8370
8371         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))
8372         {
8373                 Cvar_SetValueQuick(&r_hdr, 0);
8374                 Cvar_SetValueQuick(&r_bloom, 0);
8375                 Cvar_SetValueQuick(&r_motionblur, 0);
8376                 Cvar_SetValueQuick(&r_damageblur, 0);
8377         }
8378
8379         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)))
8380                 screentexturewidth = screentextureheight = 0;
8381         if (!r_hdr.integer && !r_bloom.integer)
8382                 bloomtexturewidth = bloomtextureheight = 0;
8383
8384         // allocate textures as needed
8385         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8386         {
8387                 if (r_bloomstate.texture_screen)
8388                         R_FreeTexture(r_bloomstate.texture_screen);
8389                 r_bloomstate.texture_screen = NULL;
8390                 r_bloomstate.screentexturewidth = screentexturewidth;
8391                 r_bloomstate.screentextureheight = screentextureheight;
8392                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8393                         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);
8394         }
8395         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8396         {
8397                 if (r_bloomstate.texture_bloom)
8398                         R_FreeTexture(r_bloomstate.texture_bloom);
8399                 r_bloomstate.texture_bloom = NULL;
8400                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8401                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8402                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8403                         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);
8404         }
8405
8406         // when doing a reduced render (HDR) we want to use a smaller area
8407         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8408         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8409         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8410         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8411         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8412
8413         // set up a texcoord array for the full resolution screen image
8414         // (we have to keep this around to copy back during final render)
8415         r_bloomstate.screentexcoord2f[0] = 0;
8416         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8417         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8418         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8419         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8420         r_bloomstate.screentexcoord2f[5] = 0;
8421         r_bloomstate.screentexcoord2f[6] = 0;
8422         r_bloomstate.screentexcoord2f[7] = 0;
8423
8424         // set up a texcoord array for the reduced resolution bloom image
8425         // (which will be additive blended over the screen image)
8426         r_bloomstate.bloomtexcoord2f[0] = 0;
8427         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8428         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8429         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8430         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8431         r_bloomstate.bloomtexcoord2f[5] = 0;
8432         r_bloomstate.bloomtexcoord2f[6] = 0;
8433         r_bloomstate.bloomtexcoord2f[7] = 0;
8434
8435         switch(vid.renderpath)
8436         {
8437         case RENDERPATH_GL11:
8438         case RENDERPATH_GL13:
8439         case RENDERPATH_GL20:
8440         case RENDERPATH_SOFT:
8441         case RENDERPATH_GLES2:
8442                 break;
8443         case RENDERPATH_D3D9:
8444         case RENDERPATH_D3D10:
8445         case RENDERPATH_D3D11:
8446                 {
8447                         int i;
8448                         for (i = 0;i < 4;i++)
8449                         {
8450                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8451                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8452                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8453                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8454                         }
8455                 }
8456                 break;
8457         }
8458
8459         if (r_hdr.integer || r_bloom.integer)
8460         {
8461                 r_bloomstate.enabled = true;
8462                 r_bloomstate.hdr = r_hdr.integer != 0;
8463         }
8464
8465         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);
8466 }
8467
8468 void R_Bloom_CopyBloomTexture(float colorscale)
8469 {
8470         r_refdef.stats.bloom++;
8471
8472         // scale down screen texture to the bloom texture size
8473         CHECKGLERROR
8474         R_SetViewport(&r_bloomstate.viewport);
8475         GL_BlendFunc(GL_ONE, GL_ZERO);
8476         GL_Color(colorscale, colorscale, colorscale, 1);
8477         // 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...
8478         switch(vid.renderpath)
8479         {
8480         case RENDERPATH_GL11:
8481         case RENDERPATH_GL13:
8482         case RENDERPATH_GL20:
8483         case RENDERPATH_SOFT:
8484         case RENDERPATH_GLES2:
8485                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8486                 break;
8487         case RENDERPATH_D3D9:
8488         case RENDERPATH_D3D10:
8489         case RENDERPATH_D3D11:
8490                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8491                 break;
8492         }
8493         // TODO: do boxfilter scale-down in shader?
8494         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8495         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8496         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8497
8498         // we now have a bloom image in the framebuffer
8499         // copy it into the bloom image texture for later processing
8500         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);
8501         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8502 }
8503
8504 void R_Bloom_CopyHDRTexture(void)
8505 {
8506         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);
8507         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8508 }
8509
8510 void R_Bloom_MakeTexture(void)
8511 {
8512         int x, range, dir;
8513         float xoffset, yoffset, r, brighten;
8514
8515         r_refdef.stats.bloom++;
8516
8517         R_ResetViewRendering2D();
8518
8519         // we have a bloom image in the framebuffer
8520         CHECKGLERROR
8521         R_SetViewport(&r_bloomstate.viewport);
8522
8523         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8524         {
8525                 x *= 2;
8526                 r = bound(0, r_bloom_colorexponent.value / x, 1);
8527                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8528                 GL_Color(r,r,r,1);
8529                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8530                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8531                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8532                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8533
8534                 // copy the vertically blurred bloom view to a texture
8535                 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);
8536                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8537         }
8538
8539         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8540         brighten = r_bloom_brighten.value;
8541         if (r_hdr.integer)
8542                 brighten *= r_hdr_range.value;
8543         brighten = sqrt(brighten);
8544         if(range >= 1)
8545                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8546         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8547
8548         for (dir = 0;dir < 2;dir++)
8549         {
8550                 // blend on at multiple vertical offsets to achieve a vertical blur
8551                 // TODO: do offset blends using GLSL
8552                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8553                 GL_BlendFunc(GL_ONE, GL_ZERO);
8554                 for (x = -range;x <= range;x++)
8555                 {
8556                         if (!dir){xoffset = 0;yoffset = x;}
8557                         else {xoffset = x;yoffset = 0;}
8558                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
8559                         yoffset /= (float)r_bloomstate.bloomtextureheight;
8560                         // compute a texcoord array with the specified x and y offset
8561                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8562                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8563                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8564                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8565                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8566                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8567                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8568                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8569                         // this r value looks like a 'dot' particle, fading sharply to
8570                         // black at the edges
8571                         // (probably not realistic but looks good enough)
8572                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8573                         //r = brighten/(range*2+1);
8574                         r = brighten / (range * 2 + 1);
8575                         if(range >= 1)
8576                                 r *= (1 - x*x/(float)(range*range));
8577                         GL_Color(r, r, r, 1);
8578                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8579                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8580                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8581                         GL_BlendFunc(GL_ONE, GL_ONE);
8582                 }
8583
8584                 // copy the vertically blurred bloom view to a texture
8585                 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);
8586                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8587         }
8588 }
8589
8590 void R_HDR_RenderBloomTexture(void)
8591 {
8592         int oldwidth, oldheight;
8593         float oldcolorscale;
8594         qboolean oldwaterstate;
8595
8596         oldwaterstate = r_waterstate.enabled;
8597         oldcolorscale = r_refdef.view.colorscale;
8598         oldwidth = r_refdef.view.width;
8599         oldheight = r_refdef.view.height;
8600         r_refdef.view.width = r_bloomstate.bloomwidth;
8601         r_refdef.view.height = r_bloomstate.bloomheight;
8602
8603         if(r_hdr.integer < 2)
8604                 r_waterstate.enabled = false;
8605
8606         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
8607         // TODO: add exposure compensation features
8608         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8609
8610         r_refdef.view.showdebug = false;
8611         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8612
8613         R_ResetViewRendering3D();
8614
8615         R_ClearScreen(r_refdef.fogenabled);
8616         if (r_timereport_active)
8617                 R_TimeReport("HDRclear");
8618
8619         R_View_Update();
8620         if (r_timereport_active)
8621                 R_TimeReport("visibility");
8622
8623         // only do secondary renders with HDR if r_hdr is 2 or higher
8624         r_waterstate.numwaterplanes = 0;
8625         if (r_waterstate.enabled)
8626                 R_RenderWaterPlanes();
8627
8628         r_refdef.view.showdebug = true;
8629         R_RenderScene();
8630         r_waterstate.numwaterplanes = 0;
8631
8632         R_ResetViewRendering2D();
8633
8634         R_Bloom_CopyHDRTexture();
8635         R_Bloom_MakeTexture();
8636
8637         // restore the view settings
8638         r_waterstate.enabled = oldwaterstate;
8639         r_refdef.view.width = oldwidth;
8640         r_refdef.view.height = oldheight;
8641         r_refdef.view.colorscale = oldcolorscale;
8642
8643         R_ResetViewRendering3D();
8644
8645         R_ClearScreen(r_refdef.fogenabled);
8646         if (r_timereport_active)
8647                 R_TimeReport("viewclear");
8648 }
8649
8650 static void R_BlendView(void)
8651 {
8652         unsigned int permutation;
8653         float uservecs[4][4];
8654
8655         switch (vid.renderpath)
8656         {
8657         case RENDERPATH_GL20:
8658         case RENDERPATH_D3D9:
8659         case RENDERPATH_D3D10:
8660         case RENDERPATH_D3D11:
8661         case RENDERPATH_SOFT:
8662         case RENDERPATH_GLES2:
8663                 permutation =
8664                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8665                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8666                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8667                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8668                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8669
8670                 if (r_bloomstate.texture_screen)
8671                 {
8672                         // make sure the buffer is available
8673                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8674
8675                         R_ResetViewRendering2D();
8676
8677                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8678                         {
8679                                 // declare variables
8680                                 float speed;
8681                                 static float avgspeed;
8682
8683                                 speed = VectorLength(cl.movement_velocity);
8684
8685                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8686                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8687
8688                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8689                                 speed = bound(0, speed, 1);
8690                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8691
8692                                 // calculate values into a standard alpha
8693                                 cl.motionbluralpha = 1 - exp(-
8694                                                 (
8695                                                  (r_motionblur.value * speed / 80)
8696                                                  +
8697                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8698                                                 )
8699                                                 /
8700                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
8701                                            );
8702
8703                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8704                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8705                                 // apply the blur
8706                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8707                                 {
8708                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8709                                         GL_Color(1, 1, 1, cl.motionbluralpha);
8710                                         switch(vid.renderpath)
8711                                         {
8712                                         case RENDERPATH_GL11:
8713                                         case RENDERPATH_GL13:
8714                                         case RENDERPATH_GL20:
8715                                         case RENDERPATH_SOFT:
8716                                         case RENDERPATH_GLES2:
8717                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8718                                                 break;
8719                                         case RENDERPATH_D3D9:
8720                                         case RENDERPATH_D3D10:
8721                                         case RENDERPATH_D3D11:
8722                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8723                                                 break;
8724                                         }
8725                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8726                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8727                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8728                                 }
8729                         }
8730
8731                         // copy view into the screen texture
8732                         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);
8733                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8734                 }
8735                 else if (!r_bloomstate.texture_bloom)
8736                 {
8737                         // we may still have to do view tint...
8738                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8739                         {
8740                                 // apply a color tint to the whole view
8741                                 R_ResetViewRendering2D();
8742                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8743                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8744                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8745                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8746                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8747                         }
8748                         break; // no screen processing, no bloom, skip it
8749                 }
8750
8751                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8752                 {
8753                         // render simple bloom effect
8754                         // copy the screen and shrink it and darken it for the bloom process
8755                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8756                         // make the bloom texture
8757                         R_Bloom_MakeTexture();
8758                 }
8759
8760 #if _MSC_VER >= 1400
8761 #define sscanf sscanf_s
8762 #endif
8763                 memset(uservecs, 0, sizeof(uservecs));
8764                 if (r_glsl_postprocess_uservec1_enable.integer)
8765                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8766                 if (r_glsl_postprocess_uservec2_enable.integer)
8767                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8768                 if (r_glsl_postprocess_uservec3_enable.integer)
8769                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8770                 if (r_glsl_postprocess_uservec4_enable.integer)
8771                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8772
8773                 R_ResetViewRendering2D();
8774                 GL_Color(1, 1, 1, 1);
8775                 GL_BlendFunc(GL_ONE, GL_ZERO);
8776
8777                 switch(vid.renderpath)
8778                 {
8779                 case RENDERPATH_GL20:
8780                 case RENDERPATH_GLES2:
8781                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8782                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8783                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
8784                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
8785                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
8786                         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]);
8787                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8788                         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]);
8789                         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]);
8790                         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]);
8791                         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]);
8792                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
8793                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8794                         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);
8795                         break;
8796                 case RENDERPATH_D3D9:
8797 #ifdef SUPPORTD3D
8798                         // 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...
8799                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8800                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
8801                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
8802                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
8803                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
8804                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8805                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8806                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8807                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8808                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8809                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8810                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
8811                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
8812                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8813 #endif
8814                         break;
8815                 case RENDERPATH_D3D10:
8816                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8817                         break;
8818                 case RENDERPATH_D3D11:
8819                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8820                         break;
8821                 case RENDERPATH_SOFT:
8822                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8823                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
8824                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
8825                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
8826                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
8827                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8828                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8829                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8830                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8831                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8832                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8833                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
8834                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8835                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8836                         break;
8837                 default:
8838                         break;
8839                 }
8840                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8841                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8842                 break;
8843         case RENDERPATH_GL13:
8844         case RENDERPATH_GL11:
8845                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8846                 {
8847                         // apply a color tint to the whole view
8848                         R_ResetViewRendering2D();
8849                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8850                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8851                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8852                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8853                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8854                 }
8855                 break;
8856         }
8857 }
8858
8859 matrix4x4_t r_waterscrollmatrix;
8860
8861 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8862 {
8863         if (r_refdef.fog_density)
8864         {
8865                 r_refdef.fogcolor[0] = r_refdef.fog_red;
8866                 r_refdef.fogcolor[1] = r_refdef.fog_green;
8867                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8868
8869                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8870                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
8871                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
8872                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
8873
8874                 {
8875                         vec3_t fogvec;
8876                         VectorCopy(r_refdef.fogcolor, fogvec);
8877                         //   color.rgb *= ContrastBoost * SceneBrightness;
8878                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
8879                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
8880                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
8881                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
8882                 }
8883         }
8884 }
8885
8886 void R_UpdateVariables(void)
8887 {
8888         R_Textures_Frame();
8889
8890         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8891
8892         r_refdef.farclip = r_farclip_base.value;
8893         if (r_refdef.scene.worldmodel)
8894                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8895         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8896
8897         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8898                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8899         r_refdef.polygonfactor = 0;
8900         r_refdef.polygonoffset = 0;
8901         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8902         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8903
8904         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8905         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8906         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
8907         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8908         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8909         if (FAKELIGHT_ENABLED)
8910         {
8911                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
8912         }
8913         if (r_showsurfaces.integer)
8914         {
8915                 r_refdef.scene.rtworld = false;
8916                 r_refdef.scene.rtworldshadows = false;
8917                 r_refdef.scene.rtdlight = false;
8918                 r_refdef.scene.rtdlightshadows = false;
8919                 r_refdef.lightmapintensity = 0;
8920         }
8921
8922         if (gamemode == GAME_NEHAHRA)
8923         {
8924                 if (gl_fogenable.integer)
8925                 {
8926                         r_refdef.oldgl_fogenable = true;
8927                         r_refdef.fog_density = gl_fogdensity.value;
8928                         r_refdef.fog_red = gl_fogred.value;
8929                         r_refdef.fog_green = gl_foggreen.value;
8930                         r_refdef.fog_blue = gl_fogblue.value;
8931                         r_refdef.fog_alpha = 1;
8932                         r_refdef.fog_start = 0;
8933                         r_refdef.fog_end = gl_skyclip.value;
8934                         r_refdef.fog_height = 1<<30;
8935                         r_refdef.fog_fadedepth = 128;
8936                 }
8937                 else if (r_refdef.oldgl_fogenable)
8938                 {
8939                         r_refdef.oldgl_fogenable = false;
8940                         r_refdef.fog_density = 0;
8941                         r_refdef.fog_red = 0;
8942                         r_refdef.fog_green = 0;
8943                         r_refdef.fog_blue = 0;
8944                         r_refdef.fog_alpha = 0;
8945                         r_refdef.fog_start = 0;
8946                         r_refdef.fog_end = 0;
8947                         r_refdef.fog_height = 1<<30;
8948                         r_refdef.fog_fadedepth = 128;
8949                 }
8950         }
8951
8952         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8953         r_refdef.fog_start = max(0, r_refdef.fog_start);
8954         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8955
8956         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8957
8958         if (r_refdef.fog_density && r_drawfog.integer)
8959         {
8960                 r_refdef.fogenabled = true;
8961                 // this is the point where the fog reaches 0.9986 alpha, which we
8962                 // consider a good enough cutoff point for the texture
8963                 // (0.9986 * 256 == 255.6)
8964                 if (r_fog_exp2.integer)
8965                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
8966                 else
8967                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
8968                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
8969                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
8970                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
8971                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
8972                         R_BuildFogHeightTexture();
8973                 // fog color was already set
8974                 // update the fog texture
8975                 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)
8976                         R_BuildFogTexture();
8977                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
8978                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
8979         }
8980         else
8981                 r_refdef.fogenabled = false;
8982
8983         switch(vid.renderpath)
8984         {
8985         case RENDERPATH_GL20:
8986         case RENDERPATH_D3D9:
8987         case RENDERPATH_D3D10:
8988         case RENDERPATH_D3D11:
8989         case RENDERPATH_SOFT:
8990         case RENDERPATH_GLES2:
8991                 if(v_glslgamma.integer && !vid_gammatables_trivial)
8992                 {
8993                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
8994                         {
8995                                 // build GLSL gamma texture
8996 #define RAMPWIDTH 256
8997                                 unsigned short ramp[RAMPWIDTH * 3];
8998                                 unsigned char rampbgr[RAMPWIDTH][4];
8999                                 int i;
9000
9001                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9002
9003                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9004                                 for(i = 0; i < RAMPWIDTH; ++i)
9005                                 {
9006                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9007                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9008                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9009                                         rampbgr[i][3] = 0;
9010                                 }
9011                                 if (r_texture_gammaramps)
9012                                 {
9013                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9014                                 }
9015                                 else
9016                                 {
9017                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9018                                 }
9019                         }
9020                 }
9021                 else
9022                 {
9023                         // remove GLSL gamma texture
9024                 }
9025                 break;
9026         case RENDERPATH_GL13:
9027         case RENDERPATH_GL11:
9028                 break;
9029         }
9030 }
9031
9032 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9033 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9034 /*
9035 ================
9036 R_SelectScene
9037 ================
9038 */
9039 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9040         if( scenetype != r_currentscenetype ) {
9041                 // store the old scenetype
9042                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9043                 r_currentscenetype = scenetype;
9044                 // move in the new scene
9045                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9046         }
9047 }
9048
9049 /*
9050 ================
9051 R_GetScenePointer
9052 ================
9053 */
9054 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9055 {
9056         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9057         if( scenetype == r_currentscenetype ) {
9058                 return &r_refdef.scene;
9059         } else {
9060                 return &r_scenes_store[ scenetype ];
9061         }
9062 }
9063
9064 /*
9065 ================
9066 R_RenderView
9067 ================
9068 */
9069 int dpsoftrast_test;
9070 void R_RenderView(void)
9071 {
9072         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9073
9074         dpsoftrast_test = r_test.integer;
9075
9076         if (r_timereport_active)
9077                 R_TimeReport("start");
9078         r_textureframe++; // used only by R_GetCurrentTexture
9079         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9080
9081         if(R_CompileShader_CheckStaticParms())
9082                 R_GLSL_Restart_f();
9083
9084         if (!r_drawentities.integer)
9085                 r_refdef.scene.numentities = 0;
9086
9087         R_AnimCache_ClearCache();
9088         R_FrameData_NewFrame();
9089
9090         /* adjust for stereo display */
9091         if(R_Stereo_Active())
9092         {
9093                 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);
9094                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9095         }
9096
9097         if (r_refdef.view.isoverlay)
9098         {
9099                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9100                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9101                 R_TimeReport("depthclear");
9102
9103                 r_refdef.view.showdebug = false;
9104
9105                 r_waterstate.enabled = false;
9106                 r_waterstate.numwaterplanes = 0;
9107
9108                 R_RenderScene();
9109
9110                 r_refdef.view.matrix = originalmatrix;
9111
9112                 CHECKGLERROR
9113                 return;
9114         }
9115
9116         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9117         {
9118                 r_refdef.view.matrix = originalmatrix;
9119                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9120         }
9121
9122         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9123
9124         R_RenderView_UpdateViewVectors();
9125
9126         R_Shadow_UpdateWorldLightSelection();
9127
9128         R_Bloom_StartFrame();
9129         R_Water_StartFrame();
9130
9131         CHECKGLERROR
9132         if (r_timereport_active)
9133                 R_TimeReport("viewsetup");
9134
9135         R_ResetViewRendering3D();
9136
9137         if (r_refdef.view.clear || r_refdef.fogenabled)
9138         {
9139                 R_ClearScreen(r_refdef.fogenabled);
9140                 if (r_timereport_active)
9141                         R_TimeReport("viewclear");
9142         }
9143         r_refdef.view.clear = true;
9144
9145         // this produces a bloom texture to be used in R_BlendView() later
9146         if (r_hdr.integer && r_bloomstate.bloomwidth)
9147         {
9148                 R_HDR_RenderBloomTexture();
9149                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9150                 r_textureframe++; // used only by R_GetCurrentTexture
9151         }
9152
9153         r_refdef.view.showdebug = true;
9154
9155         R_View_Update();
9156         if (r_timereport_active)
9157                 R_TimeReport("visibility");
9158
9159         r_waterstate.numwaterplanes = 0;
9160         if (r_waterstate.enabled)
9161                 R_RenderWaterPlanes();
9162
9163         R_RenderScene();
9164         r_waterstate.numwaterplanes = 0;
9165
9166         R_BlendView();
9167         if (r_timereport_active)
9168                 R_TimeReport("blendview");
9169
9170         GL_Scissor(0, 0, vid.width, vid.height);
9171         GL_ScissorTest(false);
9172
9173         r_refdef.view.matrix = originalmatrix;
9174
9175         CHECKGLERROR
9176 }
9177
9178 void R_RenderWaterPlanes(void)
9179 {
9180         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9181         {
9182                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9183                 if (r_timereport_active)
9184                         R_TimeReport("waterworld");
9185         }
9186
9187         // don't let sound skip if going slow
9188         if (r_refdef.scene.extraupdate)
9189                 S_ExtraUpdate ();
9190
9191         R_DrawModelsAddWaterPlanes();
9192         if (r_timereport_active)
9193                 R_TimeReport("watermodels");
9194
9195         if (r_waterstate.numwaterplanes)
9196         {
9197                 R_Water_ProcessPlanes();
9198                 if (r_timereport_active)
9199                         R_TimeReport("waterscenes");
9200         }
9201 }
9202
9203 extern void R_DrawLightningBeams (void);
9204 extern void VM_CL_AddPolygonsToMeshQueue (void);
9205 extern void R_DrawPortals (void);
9206 extern cvar_t cl_locs_show;
9207 static void R_DrawLocs(void);
9208 static void R_DrawEntityBBoxes(void);
9209 static void R_DrawModelDecals(void);
9210 extern void R_DrawModelShadows(void);
9211 extern void R_DrawModelShadowMaps(void);
9212 extern cvar_t cl_decals_newsystem;
9213 extern qboolean r_shadow_usingdeferredprepass;
9214 void R_RenderScene(void)
9215 {
9216         qboolean shadowmapping = false;
9217
9218         if (r_timereport_active)
9219                 R_TimeReport("beginscene");
9220
9221         r_refdef.stats.renders++;
9222
9223         R_UpdateFogColor();
9224
9225         // don't let sound skip if going slow
9226         if (r_refdef.scene.extraupdate)
9227                 S_ExtraUpdate ();
9228
9229         R_MeshQueue_BeginScene();
9230
9231         R_SkyStartFrame();
9232
9233         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);
9234
9235         if (r_timereport_active)
9236                 R_TimeReport("skystartframe");
9237
9238         if (cl.csqc_vidvars.drawworld)
9239         {
9240                 // don't let sound skip if going slow
9241                 if (r_refdef.scene.extraupdate)
9242                         S_ExtraUpdate ();
9243
9244                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9245                 {
9246                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9247                         if (r_timereport_active)
9248                                 R_TimeReport("worldsky");
9249                 }
9250
9251                 if (R_DrawBrushModelsSky() && r_timereport_active)
9252                         R_TimeReport("bmodelsky");
9253
9254                 if (skyrendermasked && skyrenderlater)
9255                 {
9256                         // we have to force off the water clipping plane while rendering sky
9257                         R_SetupView(false);
9258                         R_Sky();
9259                         R_SetupView(true);
9260                         if (r_timereport_active)
9261                                 R_TimeReport("sky");
9262                 }
9263         }
9264
9265         R_AnimCache_CacheVisibleEntities();
9266         if (r_timereport_active)
9267                 R_TimeReport("animation");
9268
9269         R_Shadow_PrepareLights();
9270         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9271                 R_Shadow_PrepareModelShadows();
9272         if (r_timereport_active)
9273                 R_TimeReport("preparelights");
9274
9275         if (R_Shadow_ShadowMappingEnabled())
9276                 shadowmapping = true;
9277
9278         if (r_shadow_usingdeferredprepass)
9279                 R_Shadow_DrawPrepass();
9280
9281         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9282         {
9283                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9284                 if (r_timereport_active)
9285                         R_TimeReport("worlddepth");
9286         }
9287         if (r_depthfirst.integer >= 2)
9288         {
9289                 R_DrawModelsDepth();
9290                 if (r_timereport_active)
9291                         R_TimeReport("modeldepth");
9292         }
9293
9294         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9295         {
9296                 R_DrawModelShadowMaps();
9297                 R_ResetViewRendering3D();
9298                 // don't let sound skip if going slow
9299                 if (r_refdef.scene.extraupdate)
9300                         S_ExtraUpdate ();
9301         }
9302
9303         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9304         {
9305                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9306                 if (r_timereport_active)
9307                         R_TimeReport("world");
9308         }
9309
9310         // don't let sound skip if going slow
9311         if (r_refdef.scene.extraupdate)
9312                 S_ExtraUpdate ();
9313
9314         R_DrawModels();
9315         if (r_timereport_active)
9316                 R_TimeReport("models");
9317
9318         // don't let sound skip if going slow
9319         if (r_refdef.scene.extraupdate)
9320                 S_ExtraUpdate ();
9321
9322         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9323         {
9324                 R_DrawModelShadows();
9325                 R_ResetViewRendering3D();
9326                 // don't let sound skip if going slow
9327                 if (r_refdef.scene.extraupdate)
9328                         S_ExtraUpdate ();
9329         }
9330
9331         if (!r_shadow_usingdeferredprepass)
9332         {
9333                 R_Shadow_DrawLights();
9334                 if (r_timereport_active)
9335                         R_TimeReport("rtlights");
9336         }
9337
9338         // don't let sound skip if going slow
9339         if (r_refdef.scene.extraupdate)
9340                 S_ExtraUpdate ();
9341
9342         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9343         {
9344                 R_DrawModelShadows();
9345                 R_ResetViewRendering3D();
9346                 // don't let sound skip if going slow
9347                 if (r_refdef.scene.extraupdate)
9348                         S_ExtraUpdate ();
9349         }
9350
9351         if (cl.csqc_vidvars.drawworld)
9352         {
9353                 if (cl_decals_newsystem.integer)
9354                 {
9355                         R_DrawModelDecals();
9356                         if (r_timereport_active)
9357                                 R_TimeReport("modeldecals");
9358                 }
9359                 else
9360                 {
9361                         R_DrawDecals();
9362                         if (r_timereport_active)
9363                                 R_TimeReport("decals");
9364                 }
9365
9366                 R_DrawParticles();
9367                 if (r_timereport_active)
9368                         R_TimeReport("particles");
9369
9370                 R_DrawExplosions();
9371                 if (r_timereport_active)
9372                         R_TimeReport("explosions");
9373
9374                 R_DrawLightningBeams();
9375                 if (r_timereport_active)
9376                         R_TimeReport("lightning");
9377         }
9378
9379         VM_CL_AddPolygonsToMeshQueue();
9380
9381         if (r_refdef.view.showdebug)
9382         {
9383                 if (cl_locs_show.integer)
9384                 {
9385                         R_DrawLocs();
9386                         if (r_timereport_active)
9387                                 R_TimeReport("showlocs");
9388                 }
9389
9390                 if (r_drawportals.integer)
9391                 {
9392                         R_DrawPortals();
9393                         if (r_timereport_active)
9394                                 R_TimeReport("portals");
9395                 }
9396
9397                 if (r_showbboxes.value > 0)
9398                 {
9399                         R_DrawEntityBBoxes();
9400                         if (r_timereport_active)
9401                                 R_TimeReport("bboxes");
9402                 }
9403         }
9404
9405         R_MeshQueue_RenderTransparent();
9406         if (r_timereport_active)
9407                 R_TimeReport("drawtrans");
9408
9409         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))
9410         {
9411                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9412                 if (r_timereport_active)
9413                         R_TimeReport("worlddebug");
9414                 R_DrawModelsDebug();
9415                 if (r_timereport_active)
9416                         R_TimeReport("modeldebug");
9417         }
9418
9419         if (cl.csqc_vidvars.drawworld)
9420         {
9421                 R_Shadow_DrawCoronas();
9422                 if (r_timereport_active)
9423                         R_TimeReport("coronas");
9424         }
9425
9426 #if 0
9427         {
9428                 GL_DepthTest(false);
9429                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9430                 GL_Color(1, 1, 1, 1);
9431                 qglBegin(GL_POLYGON);
9432                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9433                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9434                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9435                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9436                 qglEnd();
9437                 qglBegin(GL_POLYGON);
9438                 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]);
9439                 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]);
9440                 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]);
9441                 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]);
9442                 qglEnd();
9443                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9444         }
9445 #endif
9446
9447         // don't let sound skip if going slow
9448         if (r_refdef.scene.extraupdate)
9449                 S_ExtraUpdate ();
9450
9451         R_ResetViewRendering2D();
9452 }
9453
9454 static const unsigned short bboxelements[36] =
9455 {
9456         5, 1, 3, 5, 3, 7,
9457         6, 2, 0, 6, 0, 4,
9458         7, 3, 2, 7, 2, 6,
9459         4, 0, 1, 4, 1, 5,
9460         4, 5, 7, 4, 7, 6,
9461         1, 0, 2, 1, 2, 3,
9462 };
9463
9464 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9465 {
9466         int i;
9467         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9468
9469         RSurf_ActiveWorldEntity();
9470
9471         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9472         GL_DepthMask(false);
9473         GL_DepthRange(0, 1);
9474         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9475 //      R_Mesh_ResetTextureState();
9476
9477         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9478         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9479         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9480         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9481         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9482         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9483         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9484         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9485         R_FillColors(color4f, 8, cr, cg, cb, ca);
9486         if (r_refdef.fogenabled)
9487         {
9488                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9489                 {
9490                         f1 = RSurf_FogVertex(v);
9491                         f2 = 1 - f1;
9492                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9493                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9494                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9495                 }
9496         }
9497         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9498         R_Mesh_ResetTextureState();
9499         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9500         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9501 }
9502
9503 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9504 {
9505         int i;
9506         float color[4];
9507         prvm_edict_t *edict;
9508         prvm_prog_t *prog_save = prog;
9509
9510         // this function draws bounding boxes of server entities
9511         if (!sv.active)
9512                 return;
9513
9514         GL_CullFace(GL_NONE);
9515         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9516
9517         prog = 0;
9518         SV_VM_Begin();
9519         for (i = 0;i < numsurfaces;i++)
9520         {
9521                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9522                 switch ((int)edict->fields.server->solid)
9523                 {
9524                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9525                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9526                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9527                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9528                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9529                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9530                 }
9531                 color[3] *= r_showbboxes.value;
9532                 color[3] = bound(0, color[3], 1);
9533                 GL_DepthTest(!r_showdisabledepthtest.integer);
9534                 GL_CullFace(r_refdef.view.cullface_front);
9535                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9536         }
9537         SV_VM_End();
9538         prog = prog_save;
9539 }
9540
9541 static void R_DrawEntityBBoxes(void)
9542 {
9543         int i;
9544         prvm_edict_t *edict;
9545         vec3_t center;
9546         prvm_prog_t *prog_save = prog;
9547
9548         // this function draws bounding boxes of server entities
9549         if (!sv.active)
9550                 return;
9551
9552         prog = 0;
9553         SV_VM_Begin();
9554         for (i = 0;i < prog->num_edicts;i++)
9555         {
9556                 edict = PRVM_EDICT_NUM(i);
9557                 if (edict->priv.server->free)
9558                         continue;
9559                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9560                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9561                         continue;
9562                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9563                         continue;
9564                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9565                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9566         }
9567         SV_VM_End();
9568         prog = prog_save;
9569 }
9570
9571 static const int nomodelelement3i[24] =
9572 {
9573         5, 2, 0,
9574         5, 1, 2,
9575         5, 0, 3,
9576         5, 3, 1,
9577         0, 2, 4,
9578         2, 1, 4,
9579         3, 0, 4,
9580         1, 3, 4
9581 };
9582
9583 static const unsigned short nomodelelement3s[24] =
9584 {
9585         5, 2, 0,
9586         5, 1, 2,
9587         5, 0, 3,
9588         5, 3, 1,
9589         0, 2, 4,
9590         2, 1, 4,
9591         3, 0, 4,
9592         1, 3, 4
9593 };
9594
9595 static const float nomodelvertex3f[6*3] =
9596 {
9597         -16,   0,   0,
9598          16,   0,   0,
9599           0, -16,   0,
9600           0,  16,   0,
9601           0,   0, -16,
9602           0,   0,  16
9603 };
9604
9605 static const float nomodelcolor4f[6*4] =
9606 {
9607         0.0f, 0.0f, 0.5f, 1.0f,
9608         0.0f, 0.0f, 0.5f, 1.0f,
9609         0.0f, 0.5f, 0.0f, 1.0f,
9610         0.0f, 0.5f, 0.0f, 1.0f,
9611         0.5f, 0.0f, 0.0f, 1.0f,
9612         0.5f, 0.0f, 0.0f, 1.0f
9613 };
9614
9615 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9616 {
9617         int i;
9618         float f1, f2, *c;
9619         float color4f[6*4];
9620
9621         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);
9622
9623         // this is only called once per entity so numsurfaces is always 1, and
9624         // surfacelist is always {0}, so this code does not handle batches
9625
9626         if (rsurface.ent_flags & RENDER_ADDITIVE)
9627         {
9628                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9629                 GL_DepthMask(false);
9630         }
9631         else if (rsurface.colormod[3] < 1)
9632         {
9633                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9634                 GL_DepthMask(false);
9635         }
9636         else
9637         {
9638                 GL_BlendFunc(GL_ONE, GL_ZERO);
9639                 GL_DepthMask(true);
9640         }
9641         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9642         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9643         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9644         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9645         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9646         for (i = 0, c = color4f;i < 6;i++, c += 4)
9647         {
9648                 c[0] *= rsurface.colormod[0];
9649                 c[1] *= rsurface.colormod[1];
9650                 c[2] *= rsurface.colormod[2];
9651                 c[3] *= rsurface.colormod[3];
9652         }
9653         if (r_refdef.fogenabled)
9654         {
9655                 for (i = 0, c = color4f;i < 6;i++, c += 4)
9656                 {
9657                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9658                         f2 = 1 - f1;
9659                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9660                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9661                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9662                 }
9663         }
9664 //      R_Mesh_ResetTextureState();
9665         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9666         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9667         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9668 }
9669
9670 void R_DrawNoModel(entity_render_t *ent)
9671 {
9672         vec3_t org;
9673         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9674         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9675                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9676         else
9677                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9678 }
9679
9680 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9681 {
9682         vec3_t right1, right2, diff, normal;
9683
9684         VectorSubtract (org2, org1, normal);
9685
9686         // calculate 'right' vector for start
9687         VectorSubtract (r_refdef.view.origin, org1, diff);
9688         CrossProduct (normal, diff, right1);
9689         VectorNormalize (right1);
9690
9691         // calculate 'right' vector for end
9692         VectorSubtract (r_refdef.view.origin, org2, diff);
9693         CrossProduct (normal, diff, right2);
9694         VectorNormalize (right2);
9695
9696         vert[ 0] = org1[0] + width * right1[0];
9697         vert[ 1] = org1[1] + width * right1[1];
9698         vert[ 2] = org1[2] + width * right1[2];
9699         vert[ 3] = org1[0] - width * right1[0];
9700         vert[ 4] = org1[1] - width * right1[1];
9701         vert[ 5] = org1[2] - width * right1[2];
9702         vert[ 6] = org2[0] - width * right2[0];
9703         vert[ 7] = org2[1] - width * right2[1];
9704         vert[ 8] = org2[2] - width * right2[2];
9705         vert[ 9] = org2[0] + width * right2[0];
9706         vert[10] = org2[1] + width * right2[1];
9707         vert[11] = org2[2] + width * right2[2];
9708 }
9709
9710 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)
9711 {
9712         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9713         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9714         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9715         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9716         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9717         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9718         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9719         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9720         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9721         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9722         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9723         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9724 }
9725
9726 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9727 {
9728         int i;
9729         float *vertex3f;
9730         float v[3];
9731         VectorSet(v, x, y, z);
9732         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9733                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9734                         break;
9735         if (i == mesh->numvertices)
9736         {
9737                 if (mesh->numvertices < mesh->maxvertices)
9738                 {
9739                         VectorCopy(v, vertex3f);
9740                         mesh->numvertices++;
9741                 }
9742                 return mesh->numvertices;
9743         }
9744         else
9745                 return i;
9746 }
9747
9748 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9749 {
9750         int i;
9751         int *e, element[3];
9752         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9753         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9754         e = mesh->element3i + mesh->numtriangles * 3;
9755         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9756         {
9757                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9758                 if (mesh->numtriangles < mesh->maxtriangles)
9759                 {
9760                         *e++ = element[0];
9761                         *e++ = element[1];
9762                         *e++ = element[2];
9763                         mesh->numtriangles++;
9764                 }
9765                 element[1] = element[2];
9766         }
9767 }
9768
9769 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9770 {
9771         int i;
9772         int *e, element[3];
9773         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9774         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9775         e = mesh->element3i + mesh->numtriangles * 3;
9776         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9777         {
9778                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9779                 if (mesh->numtriangles < mesh->maxtriangles)
9780                 {
9781                         *e++ = element[0];
9782                         *e++ = element[1];
9783                         *e++ = element[2];
9784                         mesh->numtriangles++;
9785                 }
9786                 element[1] = element[2];
9787         }
9788 }
9789
9790 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9791 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9792 {
9793         int planenum, planenum2;
9794         int w;
9795         int tempnumpoints;
9796         mplane_t *plane, *plane2;
9797         double maxdist;
9798         double temppoints[2][256*3];
9799         // figure out how large a bounding box we need to properly compute this brush
9800         maxdist = 0;
9801         for (w = 0;w < numplanes;w++)
9802                 maxdist = max(maxdist, fabs(planes[w].dist));
9803         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9804         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9805         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9806         {
9807                 w = 0;
9808                 tempnumpoints = 4;
9809                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9810                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9811                 {
9812                         if (planenum2 == planenum)
9813                                 continue;
9814                         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);
9815                         w = !w;
9816                 }
9817                 if (tempnumpoints < 3)
9818                         continue;
9819                 // generate elements forming a triangle fan for this polygon
9820                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9821         }
9822 }
9823
9824 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)
9825 {
9826         texturelayer_t *layer;
9827         layer = t->currentlayers + t->currentnumlayers++;
9828         layer->type = type;
9829         layer->depthmask = depthmask;
9830         layer->blendfunc1 = blendfunc1;
9831         layer->blendfunc2 = blendfunc2;
9832         layer->texture = texture;
9833         layer->texmatrix = *matrix;
9834         layer->color[0] = r;
9835         layer->color[1] = g;
9836         layer->color[2] = b;
9837         layer->color[3] = a;
9838 }
9839
9840 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
9841 {
9842         if(parms[0] == 0 && parms[1] == 0)
9843                 return false;
9844         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9845                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
9846                         return false;
9847         return true;
9848 }
9849
9850 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
9851 {
9852         double index, f;
9853         index = parms[2] + r_refdef.scene.time * parms[3];
9854         index -= floor(index);
9855         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
9856         {
9857         default:
9858         case Q3WAVEFUNC_NONE:
9859         case Q3WAVEFUNC_NOISE:
9860         case Q3WAVEFUNC_COUNT:
9861                 f = 0;
9862                 break;
9863         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
9864         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
9865         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
9866         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
9867         case Q3WAVEFUNC_TRIANGLE:
9868                 index *= 4;
9869                 f = index - floor(index);
9870                 if (index < 1)
9871                         f = f;
9872                 else if (index < 2)
9873                         f = 1 - f;
9874                 else if (index < 3)
9875                         f = -f;
9876                 else
9877                         f = -(1 - f);
9878                 break;
9879         }
9880         f = parms[0] + parms[1] * f;
9881         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9882                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
9883         return (float) f;
9884 }
9885
9886 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
9887 {
9888         int w, h, idx;
9889         float f;
9890         float tcmat[12];
9891         matrix4x4_t matrix, temp;
9892         switch(tcmod->tcmod)
9893         {
9894                 case Q3TCMOD_COUNT:
9895                 case Q3TCMOD_NONE:
9896                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9897                                 matrix = r_waterscrollmatrix;
9898                         else
9899                                 matrix = identitymatrix;
9900                         break;
9901                 case Q3TCMOD_ENTITYTRANSLATE:
9902                         // this is used in Q3 to allow the gamecode to control texcoord
9903                         // scrolling on the entity, which is not supported in darkplaces yet.
9904                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
9905                         break;
9906                 case Q3TCMOD_ROTATE:
9907                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
9908                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
9909                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
9910                         break;
9911                 case Q3TCMOD_SCALE:
9912                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
9913                         break;
9914                 case Q3TCMOD_SCROLL:
9915                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
9916                         break;
9917                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
9918                         w = (int) tcmod->parms[0];
9919                         h = (int) tcmod->parms[1];
9920                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
9921                         f = f - floor(f);
9922                         idx = (int) floor(f * w * h);
9923                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
9924                         break;
9925                 case Q3TCMOD_STRETCH:
9926                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
9927                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
9928                         break;
9929                 case Q3TCMOD_TRANSFORM:
9930                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
9931                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
9932                         VectorSet(tcmat +  6, 0                   , 0                , 1);
9933                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
9934                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
9935                         break;
9936                 case Q3TCMOD_TURBULENT:
9937                         // this is handled in the RSurf_PrepareVertices function
9938                         matrix = identitymatrix;
9939                         break;
9940         }
9941         temp = *texmatrix;
9942         Matrix4x4_Concat(texmatrix, &matrix, &temp);
9943 }
9944
9945 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
9946 {
9947         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
9948         char name[MAX_QPATH];
9949         skinframe_t *skinframe;
9950         unsigned char pixels[296*194];
9951         strlcpy(cache->name, skinname, sizeof(cache->name));
9952         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
9953         if (developer_loading.integer)
9954                 Con_Printf("loading %s\n", name);
9955         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
9956         if (!skinframe || !skinframe->base)
9957         {
9958                 unsigned char *f;
9959                 fs_offset_t filesize;
9960                 skinframe = NULL;
9961                 f = FS_LoadFile(name, tempmempool, true, &filesize);
9962                 if (f)
9963                 {
9964                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
9965                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
9966                         Mem_Free(f);
9967                 }
9968         }
9969         cache->skinframe = skinframe;
9970 }
9971
9972 texture_t *R_GetCurrentTexture(texture_t *t)
9973 {
9974         int i;
9975         const entity_render_t *ent = rsurface.entity;
9976         dp_model_t *model = ent->model;
9977         q3shaderinfo_layer_tcmod_t *tcmod;
9978
9979         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
9980                 return t->currentframe;
9981         t->update_lastrenderframe = r_textureframe;
9982         t->update_lastrenderentity = (void *)ent;
9983
9984         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
9985                 t->camera_entity = ent->entitynumber;
9986         else
9987                 t->camera_entity = 0;
9988
9989         // switch to an alternate material if this is a q1bsp animated material
9990         {
9991                 texture_t *texture = t;
9992                 int s = rsurface.ent_skinnum;
9993                 if ((unsigned int)s >= (unsigned int)model->numskins)
9994                         s = 0;
9995                 if (model->skinscenes)
9996                 {
9997                         if (model->skinscenes[s].framecount > 1)
9998                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
9999                         else
10000                                 s = model->skinscenes[s].firstframe;
10001                 }
10002                 if (s > 0)
10003                         t = t + s * model->num_surfaces;
10004                 if (t->animated)
10005                 {
10006                         // use an alternate animation if the entity's frame is not 0,
10007                         // and only if the texture has an alternate animation
10008                         if (rsurface.ent_alttextures && t->anim_total[1])
10009                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10010                         else
10011                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10012                 }
10013                 texture->currentframe = t;
10014         }
10015
10016         // update currentskinframe to be a qw skin or animation frame
10017         if (rsurface.ent_qwskin >= 0)
10018         {
10019                 i = rsurface.ent_qwskin;
10020                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10021                 {
10022                         r_qwskincache_size = cl.maxclients;
10023                         if (r_qwskincache)
10024                                 Mem_Free(r_qwskincache);
10025                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10026                 }
10027                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10028                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10029                 t->currentskinframe = r_qwskincache[i].skinframe;
10030                 if (t->currentskinframe == NULL)
10031                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10032         }
10033         else if (t->numskinframes >= 2)
10034                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10035         if (t->backgroundnumskinframes >= 2)
10036                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10037
10038         t->currentmaterialflags = t->basematerialflags;
10039         t->currentalpha = rsurface.colormod[3];
10040         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10041                 t->currentalpha *= r_wateralpha.value;
10042         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10043                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10044         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10045                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10046         if (!(rsurface.ent_flags & RENDER_LIGHT))
10047                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10048         else if (FAKELIGHT_ENABLED)
10049         {
10050                         // no modellight if using fakelight for the map
10051         }
10052         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10053         {
10054                 // pick a model lighting mode
10055                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10056                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10057                 else
10058                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10059         }
10060         if (rsurface.ent_flags & RENDER_ADDITIVE)
10061                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10062         else if (t->currentalpha < 1)
10063                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10064         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10065                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10066         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10067                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10068         if (t->backgroundnumskinframes)
10069                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10070         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10071         {
10072                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10073                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10074         }
10075         else
10076                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10077         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10078                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10079
10080         // there is no tcmod
10081         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10082         {
10083                 t->currenttexmatrix = r_waterscrollmatrix;
10084                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10085         }
10086         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10087         {
10088                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10089                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10090         }
10091
10092         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10093                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10094         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10095                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10096
10097         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10098         if (t->currentskinframe->qpixels)
10099                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10100         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10101         if (!t->basetexture)
10102                 t->basetexture = r_texture_notexture;
10103         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10104         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10105         t->nmaptexture = t->currentskinframe->nmap;
10106         if (!t->nmaptexture)
10107                 t->nmaptexture = r_texture_blanknormalmap;
10108         t->glosstexture = r_texture_black;
10109         t->glowtexture = t->currentskinframe->glow;
10110         t->fogtexture = t->currentskinframe->fog;
10111         t->reflectmasktexture = t->currentskinframe->reflect;
10112         if (t->backgroundnumskinframes)
10113         {
10114                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10115                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10116                 t->backgroundglosstexture = r_texture_black;
10117                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10118                 if (!t->backgroundnmaptexture)
10119                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10120         }
10121         else
10122         {
10123                 t->backgroundbasetexture = r_texture_white;
10124                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10125                 t->backgroundglosstexture = r_texture_black;
10126                 t->backgroundglowtexture = NULL;
10127         }
10128         t->specularpower = r_shadow_glossexponent.value;
10129         // TODO: store reference values for these in the texture?
10130         t->specularscale = 0;
10131         if (r_shadow_gloss.integer > 0)
10132         {
10133                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10134                 {
10135                         if (r_shadow_glossintensity.value > 0)
10136                         {
10137                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10138                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10139                                 t->specularscale = r_shadow_glossintensity.value;
10140                         }
10141                 }
10142                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10143                 {
10144                         t->glosstexture = r_texture_white;
10145                         t->backgroundglosstexture = r_texture_white;
10146                         t->specularscale = r_shadow_gloss2intensity.value;
10147                         t->specularpower = r_shadow_gloss2exponent.value;
10148                 }
10149         }
10150         t->specularscale *= t->specularscalemod;
10151         t->specularpower *= t->specularpowermod;
10152
10153         // lightmaps mode looks bad with dlights using actual texturing, so turn
10154         // off the colormap and glossmap, but leave the normalmap on as it still
10155         // accurately represents the shading involved
10156         if (gl_lightmaps.integer)
10157         {
10158                 t->basetexture = r_texture_grey128;
10159                 t->pantstexture = r_texture_black;
10160                 t->shirttexture = r_texture_black;
10161                 t->nmaptexture = r_texture_blanknormalmap;
10162                 t->glosstexture = r_texture_black;
10163                 t->glowtexture = NULL;
10164                 t->fogtexture = NULL;
10165                 t->reflectmasktexture = NULL;
10166                 t->backgroundbasetexture = NULL;
10167                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10168                 t->backgroundglosstexture = r_texture_black;
10169                 t->backgroundglowtexture = NULL;
10170                 t->specularscale = 0;
10171                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10172         }
10173
10174         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10175         VectorClear(t->dlightcolor);
10176         t->currentnumlayers = 0;
10177         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10178         {
10179                 int blendfunc1, blendfunc2;
10180                 qboolean depthmask;
10181                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10182                 {
10183                         blendfunc1 = GL_SRC_ALPHA;
10184                         blendfunc2 = GL_ONE;
10185                 }
10186                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10187                 {
10188                         blendfunc1 = GL_SRC_ALPHA;
10189                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10190                 }
10191                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10192                 {
10193                         blendfunc1 = t->customblendfunc[0];
10194                         blendfunc2 = t->customblendfunc[1];
10195                 }
10196                 else
10197                 {
10198                         blendfunc1 = GL_ONE;
10199                         blendfunc2 = GL_ZERO;
10200                 }
10201                 // don't colormod evilblend textures
10202                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10203                         VectorSet(t->lightmapcolor, 1, 1, 1);
10204                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10205                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10206                 {
10207                         // fullbright is not affected by r_refdef.lightmapintensity
10208                         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]);
10209                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10210                                 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]);
10211                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10212                                 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]);
10213                 }
10214                 else
10215                 {
10216                         vec3_t ambientcolor;
10217                         float colorscale;
10218                         // set the color tint used for lights affecting this surface
10219                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10220                         colorscale = 2;
10221                         // q3bsp has no lightmap updates, so the lightstylevalue that
10222                         // would normally be baked into the lightmap must be
10223                         // applied to the color
10224                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10225                         if (model->type == mod_brushq3)
10226                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10227                         colorscale *= r_refdef.lightmapintensity;
10228                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10229                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10230                         // basic lit geometry
10231                         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]);
10232                         // add pants/shirt if needed
10233                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10234                                 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]);
10235                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10236                                 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]);
10237                         // now add ambient passes if needed
10238                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10239                         {
10240                                 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]);
10241                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10242                                         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]);
10243                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10244                                         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]);
10245                         }
10246                 }
10247                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10248                         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]);
10249                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10250                 {
10251                         // if this is opaque use alpha blend which will darken the earlier
10252                         // passes cheaply.
10253                         //
10254                         // if this is an alpha blended material, all the earlier passes
10255                         // were darkened by fog already, so we only need to add the fog
10256                         // color ontop through the fog mask texture
10257                         //
10258                         // if this is an additive blended material, all the earlier passes
10259                         // were darkened by fog already, and we should not add fog color
10260                         // (because the background was not darkened, there is no fog color
10261                         // that was lost behind it).
10262                         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]);
10263                 }
10264         }
10265
10266         return t->currentframe;
10267 }
10268
10269 rsurfacestate_t rsurface;
10270
10271 void RSurf_ActiveWorldEntity(void)
10272 {
10273         dp_model_t *model = r_refdef.scene.worldmodel;
10274         //if (rsurface.entity == r_refdef.scene.worldentity)
10275         //      return;
10276         rsurface.entity = r_refdef.scene.worldentity;
10277         rsurface.skeleton = NULL;
10278         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10279         rsurface.ent_skinnum = 0;
10280         rsurface.ent_qwskin = -1;
10281         rsurface.ent_shadertime = 0;
10282         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10283         rsurface.matrix = identitymatrix;
10284         rsurface.inversematrix = identitymatrix;
10285         rsurface.matrixscale = 1;
10286         rsurface.inversematrixscale = 1;
10287         R_EntityMatrix(&identitymatrix);
10288         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10289         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10290         rsurface.fograngerecip = r_refdef.fograngerecip;
10291         rsurface.fogheightfade = r_refdef.fogheightfade;
10292         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10293         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10294         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10295         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10296         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10297         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10298         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10299         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10300         rsurface.colormod[3] = 1;
10301         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);
10302         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10303         rsurface.frameblend[0].lerp = 1;
10304         rsurface.ent_alttextures = false;
10305         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10306         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10307         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10308         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10309         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10310         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10311         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10312         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10313         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10314         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10315         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10316         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10317         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10318         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10319         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10320         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10321         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10322         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10323         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10324         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10325         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10326         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10327         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10328         rsurface.modelelement3i = model->surfmesh.data_element3i;
10329         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10330         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10331         rsurface.modelelement3s = model->surfmesh.data_element3s;
10332         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10333         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10334         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10335         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10336         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10337         rsurface.modelsurfaces = model->data_surfaces;
10338         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10339         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10340         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10341         rsurface.modelgeneratedvertex = false;
10342         rsurface.batchgeneratedvertex = false;
10343         rsurface.batchfirstvertex = 0;
10344         rsurface.batchnumvertices = 0;
10345         rsurface.batchfirsttriangle = 0;
10346         rsurface.batchnumtriangles = 0;
10347         rsurface.batchvertex3f  = NULL;
10348         rsurface.batchvertex3f_vertexbuffer = NULL;
10349         rsurface.batchvertex3f_bufferoffset = 0;
10350         rsurface.batchsvector3f = NULL;
10351         rsurface.batchsvector3f_vertexbuffer = NULL;
10352         rsurface.batchsvector3f_bufferoffset = 0;
10353         rsurface.batchtvector3f = NULL;
10354         rsurface.batchtvector3f_vertexbuffer = NULL;
10355         rsurface.batchtvector3f_bufferoffset = 0;
10356         rsurface.batchnormal3f  = NULL;
10357         rsurface.batchnormal3f_vertexbuffer = NULL;
10358         rsurface.batchnormal3f_bufferoffset = 0;
10359         rsurface.batchlightmapcolor4f = NULL;
10360         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10361         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10362         rsurface.batchtexcoordtexture2f = NULL;
10363         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10364         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10365         rsurface.batchtexcoordlightmap2f = NULL;
10366         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10367         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10368         rsurface.batchvertexmesh = NULL;
10369         rsurface.batchvertexmeshbuffer = NULL;
10370         rsurface.batchvertex3fbuffer = NULL;
10371         rsurface.batchelement3i = NULL;
10372         rsurface.batchelement3i_indexbuffer = NULL;
10373         rsurface.batchelement3i_bufferoffset = 0;
10374         rsurface.batchelement3s = NULL;
10375         rsurface.batchelement3s_indexbuffer = NULL;
10376         rsurface.batchelement3s_bufferoffset = 0;
10377         rsurface.passcolor4f = NULL;
10378         rsurface.passcolor4f_vertexbuffer = NULL;
10379         rsurface.passcolor4f_bufferoffset = 0;
10380 }
10381
10382 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10383 {
10384         dp_model_t *model = ent->model;
10385         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10386         //      return;
10387         rsurface.entity = (entity_render_t *)ent;
10388         rsurface.skeleton = ent->skeleton;
10389         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10390         rsurface.ent_skinnum = ent->skinnum;
10391         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;
10392         rsurface.ent_shadertime = ent->shadertime;
10393         rsurface.ent_flags = ent->flags;
10394         rsurface.matrix = ent->matrix;
10395         rsurface.inversematrix = ent->inversematrix;
10396         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10397         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10398         R_EntityMatrix(&rsurface.matrix);
10399         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10400         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10401         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10402         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10403         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10404         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10405         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10406         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10407         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10408         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10409         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10410         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10411         rsurface.colormod[3] = ent->alpha;
10412         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10413         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10414         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10415         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10416         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10417         if (ent->model->brush.submodel && !prepass)
10418         {
10419                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10420                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10421         }
10422         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10423         {
10424                 if (ent->animcache_vertex3f)
10425                 {
10426                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10427                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10428                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10429                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10430                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10431                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10432                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
10433                 }
10434                 else if (wanttangents)
10435                 {
10436                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10437                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10438                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10439                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10440                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
10441                         rsurface.modelvertexmesh = NULL;
10442                         rsurface.modelvertexmeshbuffer = NULL;
10443                         rsurface.modelvertex3fbuffer = NULL;
10444                 }
10445                 else if (wantnormals)
10446                 {
10447                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10448                         rsurface.modelsvector3f = NULL;
10449                         rsurface.modeltvector3f = NULL;
10450                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10451                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
10452                         rsurface.modelvertexmesh = NULL;
10453                         rsurface.modelvertexmeshbuffer = NULL;
10454                         rsurface.modelvertex3fbuffer = NULL;
10455                 }
10456                 else
10457                 {
10458                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10459                         rsurface.modelsvector3f = NULL;
10460                         rsurface.modeltvector3f = NULL;
10461                         rsurface.modelnormal3f = NULL;
10462                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
10463                         rsurface.modelvertexmesh = NULL;
10464                         rsurface.modelvertexmeshbuffer = NULL;
10465                         rsurface.modelvertex3fbuffer = NULL;
10466                 }
10467                 rsurface.modelvertex3f_vertexbuffer = 0;
10468                 rsurface.modelvertex3f_bufferoffset = 0;
10469                 rsurface.modelsvector3f_vertexbuffer = 0;
10470                 rsurface.modelsvector3f_bufferoffset = 0;
10471                 rsurface.modeltvector3f_vertexbuffer = 0;
10472                 rsurface.modeltvector3f_bufferoffset = 0;
10473                 rsurface.modelnormal3f_vertexbuffer = 0;
10474                 rsurface.modelnormal3f_bufferoffset = 0;
10475                 rsurface.modelgeneratedvertex = true;
10476         }
10477         else
10478         {
10479                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10480                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10481                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10482                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10483                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10484                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10485                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10486                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10487                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10488                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10489                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10490                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10491                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10492                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10493                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10494                 rsurface.modelgeneratedvertex = false;
10495         }
10496         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10497         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10498         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10499         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10500         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10501         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10502         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10503         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10504         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10505         rsurface.modelelement3i = model->surfmesh.data_element3i;
10506         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10507         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10508         rsurface.modelelement3s = model->surfmesh.data_element3s;
10509         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10510         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10511         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10512         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10513         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10514         rsurface.modelsurfaces = model->data_surfaces;
10515         rsurface.batchgeneratedvertex = false;
10516         rsurface.batchfirstvertex = 0;
10517         rsurface.batchnumvertices = 0;
10518         rsurface.batchfirsttriangle = 0;
10519         rsurface.batchnumtriangles = 0;
10520         rsurface.batchvertex3f  = NULL;
10521         rsurface.batchvertex3f_vertexbuffer = NULL;
10522         rsurface.batchvertex3f_bufferoffset = 0;
10523         rsurface.batchsvector3f = NULL;
10524         rsurface.batchsvector3f_vertexbuffer = NULL;
10525         rsurface.batchsvector3f_bufferoffset = 0;
10526         rsurface.batchtvector3f = NULL;
10527         rsurface.batchtvector3f_vertexbuffer = NULL;
10528         rsurface.batchtvector3f_bufferoffset = 0;
10529         rsurface.batchnormal3f  = NULL;
10530         rsurface.batchnormal3f_vertexbuffer = NULL;
10531         rsurface.batchnormal3f_bufferoffset = 0;
10532         rsurface.batchlightmapcolor4f = NULL;
10533         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10534         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10535         rsurface.batchtexcoordtexture2f = NULL;
10536         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10537         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10538         rsurface.batchtexcoordlightmap2f = NULL;
10539         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10540         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10541         rsurface.batchvertexmesh = NULL;
10542         rsurface.batchvertexmeshbuffer = NULL;
10543         rsurface.batchvertex3fbuffer = NULL;
10544         rsurface.batchelement3i = NULL;
10545         rsurface.batchelement3i_indexbuffer = NULL;
10546         rsurface.batchelement3i_bufferoffset = 0;
10547         rsurface.batchelement3s = NULL;
10548         rsurface.batchelement3s_indexbuffer = NULL;
10549         rsurface.batchelement3s_bufferoffset = 0;
10550         rsurface.passcolor4f = NULL;
10551         rsurface.passcolor4f_vertexbuffer = NULL;
10552         rsurface.passcolor4f_bufferoffset = 0;
10553 }
10554
10555 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)
10556 {
10557         rsurface.entity = r_refdef.scene.worldentity;
10558         rsurface.skeleton = NULL;
10559         rsurface.ent_skinnum = 0;
10560         rsurface.ent_qwskin = -1;
10561         rsurface.ent_shadertime = shadertime;
10562         rsurface.ent_flags = entflags;
10563         rsurface.modelnumvertices = numvertices;
10564         rsurface.modelnumtriangles = numtriangles;
10565         rsurface.matrix = *matrix;
10566         rsurface.inversematrix = *inversematrix;
10567         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10568         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10569         R_EntityMatrix(&rsurface.matrix);
10570         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10571         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10572         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10573         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10574         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10575         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10576         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10577         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10578         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10579         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10580         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10581         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10582         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);
10583         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10584         rsurface.frameblend[0].lerp = 1;
10585         rsurface.ent_alttextures = false;
10586         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10587         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10588         if (wanttangents)
10589         {
10590                 rsurface.modelvertex3f = (float *)vertex3f;
10591                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10592                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10593                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10594         }
10595         else if (wantnormals)
10596         {
10597                 rsurface.modelvertex3f = (float *)vertex3f;
10598                 rsurface.modelsvector3f = NULL;
10599                 rsurface.modeltvector3f = NULL;
10600                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10601         }
10602         else
10603         {
10604                 rsurface.modelvertex3f = (float *)vertex3f;
10605                 rsurface.modelsvector3f = NULL;
10606                 rsurface.modeltvector3f = NULL;
10607                 rsurface.modelnormal3f = NULL;
10608         }
10609         rsurface.modelvertexmesh = NULL;
10610         rsurface.modelvertexmeshbuffer = NULL;
10611         rsurface.modelvertex3fbuffer = NULL;
10612         rsurface.modelvertex3f_vertexbuffer = 0;
10613         rsurface.modelvertex3f_bufferoffset = 0;
10614         rsurface.modelsvector3f_vertexbuffer = 0;
10615         rsurface.modelsvector3f_bufferoffset = 0;
10616         rsurface.modeltvector3f_vertexbuffer = 0;
10617         rsurface.modeltvector3f_bufferoffset = 0;
10618         rsurface.modelnormal3f_vertexbuffer = 0;
10619         rsurface.modelnormal3f_bufferoffset = 0;
10620         rsurface.modelgeneratedvertex = true;
10621         rsurface.modellightmapcolor4f  = (float *)color4f;
10622         rsurface.modellightmapcolor4f_vertexbuffer = 0;
10623         rsurface.modellightmapcolor4f_bufferoffset = 0;
10624         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
10625         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
10626         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10627         rsurface.modeltexcoordlightmap2f  = NULL;
10628         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
10629         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10630         rsurface.modelelement3i = (int *)element3i;
10631         rsurface.modelelement3i_indexbuffer = NULL;
10632         rsurface.modelelement3i_bufferoffset = 0;
10633         rsurface.modelelement3s = (unsigned short *)element3s;
10634         rsurface.modelelement3s_indexbuffer = NULL;
10635         rsurface.modelelement3s_bufferoffset = 0;
10636         rsurface.modellightmapoffsets = NULL;
10637         rsurface.modelsurfaces = NULL;
10638         rsurface.batchgeneratedvertex = false;
10639         rsurface.batchfirstvertex = 0;
10640         rsurface.batchnumvertices = 0;
10641         rsurface.batchfirsttriangle = 0;
10642         rsurface.batchnumtriangles = 0;
10643         rsurface.batchvertex3f  = NULL;
10644         rsurface.batchvertex3f_vertexbuffer = NULL;
10645         rsurface.batchvertex3f_bufferoffset = 0;
10646         rsurface.batchsvector3f = NULL;
10647         rsurface.batchsvector3f_vertexbuffer = NULL;
10648         rsurface.batchsvector3f_bufferoffset = 0;
10649         rsurface.batchtvector3f = NULL;
10650         rsurface.batchtvector3f_vertexbuffer = NULL;
10651         rsurface.batchtvector3f_bufferoffset = 0;
10652         rsurface.batchnormal3f  = NULL;
10653         rsurface.batchnormal3f_vertexbuffer = NULL;
10654         rsurface.batchnormal3f_bufferoffset = 0;
10655         rsurface.batchlightmapcolor4f = NULL;
10656         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10657         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10658         rsurface.batchtexcoordtexture2f = NULL;
10659         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10660         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10661         rsurface.batchtexcoordlightmap2f = NULL;
10662         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10663         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10664         rsurface.batchvertexmesh = NULL;
10665         rsurface.batchvertexmeshbuffer = NULL;
10666         rsurface.batchvertex3fbuffer = NULL;
10667         rsurface.batchelement3i = NULL;
10668         rsurface.batchelement3i_indexbuffer = NULL;
10669         rsurface.batchelement3i_bufferoffset = 0;
10670         rsurface.batchelement3s = NULL;
10671         rsurface.batchelement3s_indexbuffer = NULL;
10672         rsurface.batchelement3s_bufferoffset = 0;
10673         rsurface.passcolor4f = NULL;
10674         rsurface.passcolor4f_vertexbuffer = NULL;
10675         rsurface.passcolor4f_bufferoffset = 0;
10676
10677         if (rsurface.modelnumvertices && rsurface.modelelement3i)
10678         {
10679                 if ((wantnormals || wanttangents) && !normal3f)
10680                 {
10681                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10682                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10683                 }
10684                 if (wanttangents && !svector3f)
10685                 {
10686                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10687                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10688                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
10689                 }
10690         }
10691 }
10692
10693 float RSurf_FogPoint(const float *v)
10694 {
10695         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10696         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10697         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10698         float FogHeightFade = r_refdef.fogheightfade;
10699         float fogfrac;
10700         unsigned int fogmasktableindex;
10701         if (r_refdef.fogplaneviewabove)
10702                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10703         else
10704                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10705         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10706         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10707 }
10708
10709 float RSurf_FogVertex(const float *v)
10710 {
10711         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10712         float FogPlaneViewDist = rsurface.fogplaneviewdist;
10713         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10714         float FogHeightFade = rsurface.fogheightfade;
10715         float fogfrac;
10716         unsigned int fogmasktableindex;
10717         if (r_refdef.fogplaneviewabove)
10718                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10719         else
10720                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10721         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10722         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10723 }
10724
10725 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
10726 {
10727         int i;
10728         for (i = 0;i < numelements;i++)
10729                 outelement3i[i] = inelement3i[i] + adjust;
10730 }
10731
10732 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
10733 extern cvar_t gl_vbo;
10734 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
10735 {
10736         int deformindex;
10737         int firsttriangle;
10738         int numtriangles;
10739         int firstvertex;
10740         int endvertex;
10741         int numvertices;
10742         int surfacefirsttriangle;
10743         int surfacenumtriangles;
10744         int surfacefirstvertex;
10745         int surfaceendvertex;
10746         int surfacenumvertices;
10747         int batchnumvertices;
10748         int batchnumtriangles;
10749         int needsupdate;
10750         int i, j;
10751         qboolean gaps;
10752         qboolean dynamicvertex;
10753         float amplitude;
10754         float animpos;
10755         float scale;
10756         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
10757         float waveparms[4];
10758         q3shaderinfo_deform_t *deform;
10759         const msurface_t *surface, *firstsurface;
10760         r_vertexmesh_t *vertexmesh;
10761         if (!texturenumsurfaces)
10762                 return;
10763         // find vertex range of this surface batch
10764         gaps = false;
10765         firstsurface = texturesurfacelist[0];
10766         firsttriangle = firstsurface->num_firsttriangle;
10767         batchnumvertices = 0;
10768         batchnumtriangles = 0;
10769         firstvertex = endvertex = firstsurface->num_firstvertex;
10770         for (i = 0;i < texturenumsurfaces;i++)
10771         {
10772                 surface = texturesurfacelist[i];
10773                 if (surface != firstsurface + i)
10774                         gaps = true;
10775                 surfacefirstvertex = surface->num_firstvertex;
10776                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
10777                 surfacenumvertices = surface->num_vertices;
10778                 surfacenumtriangles = surface->num_triangles;
10779                 if (firstvertex > surfacefirstvertex)
10780                         firstvertex = surfacefirstvertex;
10781                 if (endvertex < surfaceendvertex)
10782                         endvertex = surfaceendvertex;
10783                 batchnumvertices += surfacenumvertices;
10784                 batchnumtriangles += surfacenumtriangles;
10785         }
10786
10787         // we now know the vertex range used, and if there are any gaps in it
10788         rsurface.batchfirstvertex = firstvertex;
10789         rsurface.batchnumvertices = endvertex - firstvertex;
10790         rsurface.batchfirsttriangle = firsttriangle;
10791         rsurface.batchnumtriangles = batchnumtriangles;
10792
10793         // this variable holds flags for which properties have been updated that
10794         // may require regenerating vertexmesh array...
10795         needsupdate = 0;
10796
10797         // check if any dynamic vertex processing must occur
10798         dynamicvertex = false;
10799
10800         // if there is a chance of animated vertex colors, it's a dynamic batch
10801         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10802         {
10803                 dynamicvertex = true;
10804                 batchneed |= BATCHNEED_NOGAPS;
10805                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
10806         }
10807
10808         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10809         {
10810                 switch (deform->deform)
10811                 {
10812                 default:
10813                 case Q3DEFORM_PROJECTIONSHADOW:
10814                 case Q3DEFORM_TEXT0:
10815                 case Q3DEFORM_TEXT1:
10816                 case Q3DEFORM_TEXT2:
10817                 case Q3DEFORM_TEXT3:
10818                 case Q3DEFORM_TEXT4:
10819                 case Q3DEFORM_TEXT5:
10820                 case Q3DEFORM_TEXT6:
10821                 case Q3DEFORM_TEXT7:
10822                 case Q3DEFORM_NONE:
10823                         break;
10824                 case Q3DEFORM_AUTOSPRITE:
10825                         dynamicvertex = true;
10826                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10827                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10828                         break;
10829                 case Q3DEFORM_AUTOSPRITE2:
10830                         dynamicvertex = true;
10831                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10832                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10833                         break;
10834                 case Q3DEFORM_NORMAL:
10835                         dynamicvertex = true;
10836                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10837                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10838                         break;
10839                 case Q3DEFORM_WAVE:
10840                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10841                                 break; // if wavefunc is a nop, ignore this transform
10842                         dynamicvertex = true;
10843                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10844                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10845                         break;
10846                 case Q3DEFORM_BULGE:
10847                         dynamicvertex = true;
10848                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10849                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10850                         break;
10851                 case Q3DEFORM_MOVE:
10852                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10853                                 break; // if wavefunc is a nop, ignore this transform
10854                         dynamicvertex = true;
10855                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10856                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
10857                         break;
10858                 }
10859         }
10860         switch(rsurface.texture->tcgen.tcgen)
10861         {
10862         default:
10863         case Q3TCGEN_TEXTURE:
10864                 break;
10865         case Q3TCGEN_LIGHTMAP:
10866                 dynamicvertex = true;
10867                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
10868                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
10869                 break;
10870         case Q3TCGEN_VECTOR:
10871                 dynamicvertex = true;
10872                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10873                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10874                 break;
10875         case Q3TCGEN_ENVIRONMENT:
10876                 dynamicvertex = true;
10877                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
10878                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10879                 break;
10880         }
10881         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10882         {
10883                 dynamicvertex = true;
10884                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10885                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10886         }
10887
10888         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10889         {
10890                 dynamicvertex = true;
10891                 batchneed |= BATCHNEED_NOGAPS;
10892                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
10893         }
10894
10895         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
10896         {
10897                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
10898                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
10899                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
10900                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
10901                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
10902                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
10903                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
10904         }
10905
10906         // when the model data has no vertex buffer (dynamic mesh), we need to
10907         // eliminate gaps
10908         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
10909                 batchneed |= BATCHNEED_NOGAPS;
10910
10911         // if needsupdate, we have to do a dynamic vertex batch for sure
10912         if (needsupdate & batchneed)
10913                 dynamicvertex = true;
10914
10915         // see if we need to build vertexmesh from arrays
10916         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10917                 dynamicvertex = true;
10918
10919         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
10920         // also some drivers strongly dislike firstvertex
10921         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
10922                 dynamicvertex = true;
10923
10924         rsurface.batchvertex3f = rsurface.modelvertex3f;
10925         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
10926         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10927         rsurface.batchsvector3f = rsurface.modelsvector3f;
10928         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
10929         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10930         rsurface.batchtvector3f = rsurface.modeltvector3f;
10931         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
10932         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10933         rsurface.batchnormal3f = rsurface.modelnormal3f;
10934         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
10935         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10936         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
10937         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
10938         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
10939         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
10940         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
10941         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
10942         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
10943         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
10944         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10945         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
10946         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
10947         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
10948         rsurface.batchelement3i = rsurface.modelelement3i;
10949         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
10950         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
10951         rsurface.batchelement3s = rsurface.modelelement3s;
10952         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
10953         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
10954
10955         // if any dynamic vertex processing has to occur in software, we copy the
10956         // entire surface list together before processing to rebase the vertices
10957         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
10958         //
10959         // if any gaps exist and we do not have a static vertex buffer, we have to
10960         // copy the surface list together to avoid wasting upload bandwidth on the
10961         // vertices in the gaps.
10962         //
10963         // if gaps exist and we have a static vertex buffer, we still have to
10964         // combine the index buffer ranges into one dynamic index buffer.
10965         //
10966         // in all cases we end up with data that can be drawn in one call.
10967
10968         if (!dynamicvertex)
10969         {
10970                 // static vertex data, just set pointers...
10971                 rsurface.batchgeneratedvertex = false;
10972                 // if there are gaps, we want to build a combined index buffer,
10973                 // otherwise use the original static buffer with an appropriate offset
10974                 if (gaps)
10975                 {
10976                         // build a new triangle elements array for this batch
10977                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
10978                         rsurface.batchfirsttriangle = 0;
10979                         numtriangles = 0;
10980                         for (i = 0;i < texturenumsurfaces;i++)
10981                         {
10982                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
10983                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
10984                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
10985                                 numtriangles += surfacenumtriangles;
10986                         }
10987                         rsurface.batchelement3i_indexbuffer = NULL;
10988                         rsurface.batchelement3i_bufferoffset = 0;
10989                         rsurface.batchelement3s = NULL;
10990                         rsurface.batchelement3s_indexbuffer = NULL;
10991                         rsurface.batchelement3s_bufferoffset = 0;
10992                         if (endvertex <= 65536)
10993                         {
10994                                 // make a 16bit (unsigned short) index array if possible
10995                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
10996                                 for (i = 0;i < numtriangles*3;i++)
10997                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
10998                         }
10999                 }
11000                 return;
11001         }
11002
11003         // something needs software processing, do it for real...
11004         // we only directly handle separate array data in this case and then
11005         // generate interleaved data if needed...
11006         rsurface.batchgeneratedvertex = true;
11007
11008         // now copy the vertex data into a combined array and make an index array
11009         // (this is what Quake3 does all the time)
11010         //if (gaps || rsurface.batchfirstvertex)
11011         {
11012                 rsurface.batchvertex3fbuffer = NULL;
11013                 rsurface.batchvertexmesh = NULL;
11014                 rsurface.batchvertexmeshbuffer = NULL;
11015                 rsurface.batchvertex3f = NULL;
11016                 rsurface.batchvertex3f_vertexbuffer = NULL;
11017                 rsurface.batchvertex3f_bufferoffset = 0;
11018                 rsurface.batchsvector3f = NULL;
11019                 rsurface.batchsvector3f_vertexbuffer = NULL;
11020                 rsurface.batchsvector3f_bufferoffset = 0;
11021                 rsurface.batchtvector3f = NULL;
11022                 rsurface.batchtvector3f_vertexbuffer = NULL;
11023                 rsurface.batchtvector3f_bufferoffset = 0;
11024                 rsurface.batchnormal3f = NULL;
11025                 rsurface.batchnormal3f_vertexbuffer = NULL;
11026                 rsurface.batchnormal3f_bufferoffset = 0;
11027                 rsurface.batchlightmapcolor4f = NULL;
11028                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11029                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11030                 rsurface.batchtexcoordtexture2f = NULL;
11031                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11032                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11033                 rsurface.batchtexcoordlightmap2f = NULL;
11034                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11035                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11036                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11037                 rsurface.batchelement3i_indexbuffer = NULL;
11038                 rsurface.batchelement3i_bufferoffset = 0;
11039                 rsurface.batchelement3s = NULL;
11040                 rsurface.batchelement3s_indexbuffer = NULL;
11041                 rsurface.batchelement3s_bufferoffset = 0;
11042                 // we'll only be setting up certain arrays as needed
11043                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11044                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11045                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11046                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11047                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11048                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11049                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11050                 {
11051                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11052                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11053                 }
11054                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11055                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11056                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11057                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11058                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11059                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11060                 numvertices = 0;
11061                 numtriangles = 0;
11062                 for (i = 0;i < texturenumsurfaces;i++)
11063                 {
11064                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11065                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11066                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11067                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11068                         // copy only the data requested
11069                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11070                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11071                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11072                         {
11073                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11074                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11075                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11076                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11077                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11078                                 {
11079                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11080                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11081                                 }
11082                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11083                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11084                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11085                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11086                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11087                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11088                         }
11089                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11090                         numvertices += surfacenumvertices;
11091                         numtriangles += surfacenumtriangles;
11092                 }
11093
11094                 // generate a 16bit index array as well if possible
11095                 // (in general, dynamic batches fit)
11096                 if (numvertices <= 65536)
11097                 {
11098                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11099                         for (i = 0;i < numtriangles*3;i++)
11100                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11101                 }
11102
11103                 // since we've copied everything, the batch now starts at 0
11104                 rsurface.batchfirstvertex = 0;
11105                 rsurface.batchnumvertices = batchnumvertices;
11106                 rsurface.batchfirsttriangle = 0;
11107                 rsurface.batchnumtriangles = batchnumtriangles;
11108         }
11109
11110         // q1bsp surfaces rendered in vertex color mode have to have colors
11111         // calculated based on lightstyles
11112         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11113         {
11114                 // generate color arrays for the surfaces in this list
11115                 int c[4];
11116                 int scale;
11117                 int size3;
11118                 const int *offsets;
11119                 const unsigned char *lm;
11120                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11121                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11122                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11123                 numvertices = 0;
11124                 for (i = 0;i < texturenumsurfaces;i++)
11125                 {
11126                         surface = texturesurfacelist[i];
11127                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11128                         surfacenumvertices = surface->num_vertices;
11129                         if (surface->lightmapinfo->samples)
11130                         {
11131                                 for (j = 0;j < surfacenumvertices;j++)
11132                                 {
11133                                         lm = surface->lightmapinfo->samples + offsets[j];
11134                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11135                                         VectorScale(lm, scale, c);
11136                                         if (surface->lightmapinfo->styles[1] != 255)
11137                                         {
11138                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11139                                                 lm += size3;
11140                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11141                                                 VectorMA(c, scale, lm, c);
11142                                                 if (surface->lightmapinfo->styles[2] != 255)
11143                                                 {
11144                                                         lm += size3;
11145                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11146                                                         VectorMA(c, scale, lm, c);
11147                                                         if (surface->lightmapinfo->styles[3] != 255)
11148                                                         {
11149                                                                 lm += size3;
11150                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11151                                                                 VectorMA(c, scale, lm, c);
11152                                                         }
11153                                                 }
11154                                         }
11155                                         c[0] >>= 7;
11156                                         c[1] >>= 7;
11157                                         c[2] >>= 7;
11158                                         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);
11159                                         numvertices++;
11160                                 }
11161                         }
11162                         else
11163                         {
11164                                 for (j = 0;j < surfacenumvertices;j++)
11165                                 {
11166                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11167                                         numvertices++;
11168                                 }
11169                         }
11170                 }
11171         }
11172
11173         // if vertices are deformed (sprite flares and things in maps, possibly
11174         // water waves, bulges and other deformations), modify the copied vertices
11175         // in place
11176         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11177         {
11178                 switch (deform->deform)
11179                 {
11180                 default:
11181                 case Q3DEFORM_PROJECTIONSHADOW:
11182                 case Q3DEFORM_TEXT0:
11183                 case Q3DEFORM_TEXT1:
11184                 case Q3DEFORM_TEXT2:
11185                 case Q3DEFORM_TEXT3:
11186                 case Q3DEFORM_TEXT4:
11187                 case Q3DEFORM_TEXT5:
11188                 case Q3DEFORM_TEXT6:
11189                 case Q3DEFORM_TEXT7:
11190                 case Q3DEFORM_NONE:
11191                         break;
11192                 case Q3DEFORM_AUTOSPRITE:
11193                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11194                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11195                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11196                         VectorNormalize(newforward);
11197                         VectorNormalize(newright);
11198                         VectorNormalize(newup);
11199 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11200 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11201 //                      rsurface.batchvertex3f_bufferoffset = 0;
11202 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
11203 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
11204 //                      rsurface.batchsvector3f_bufferoffset = 0;
11205 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
11206 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
11207 //                      rsurface.batchtvector3f_bufferoffset = 0;
11208 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11209 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11210 //                      rsurface.batchnormal3f_bufferoffset = 0;
11211                         // a single autosprite surface can contain multiple sprites...
11212                         for (j = 0;j < batchnumvertices - 3;j += 4)
11213                         {
11214                                 VectorClear(center);
11215                                 for (i = 0;i < 4;i++)
11216                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11217                                 VectorScale(center, 0.25f, center);
11218                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11219                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11220                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11221                                 for (i = 0;i < 4;i++)
11222                                 {
11223                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11224                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
11225                                 }
11226                         }
11227                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11228                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11229                         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);
11230                         break;
11231                 case Q3DEFORM_AUTOSPRITE2:
11232                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11233                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11234                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11235                         VectorNormalize(newforward);
11236                         VectorNormalize(newright);
11237                         VectorNormalize(newup);
11238 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11239 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11240 //                      rsurface.batchvertex3f_bufferoffset = 0;
11241                         {
11242                                 const float *v1, *v2;
11243                                 vec3_t start, end;
11244                                 float f, l;
11245                                 struct
11246                                 {
11247                                         float length2;
11248                                         const float *v1;
11249                                         const float *v2;
11250                                 }
11251                                 shortest[2];
11252                                 memset(shortest, 0, sizeof(shortest));
11253                                 // a single autosprite surface can contain multiple sprites...
11254                                 for (j = 0;j < batchnumvertices - 3;j += 4)
11255                                 {
11256                                         VectorClear(center);
11257                                         for (i = 0;i < 4;i++)
11258                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11259                                         VectorScale(center, 0.25f, center);
11260                                         // find the two shortest edges, then use them to define the
11261                                         // axis vectors for rotating around the central axis
11262                                         for (i = 0;i < 6;i++)
11263                                         {
11264                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11265                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11266                                                 l = VectorDistance2(v1, v2);
11267                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11268                                                 if (v1[2] != v2[2])
11269                                                         l += (1.0f / 1024.0f);
11270                                                 if (shortest[0].length2 > l || i == 0)
11271                                                 {
11272                                                         shortest[1] = shortest[0];
11273                                                         shortest[0].length2 = l;
11274                                                         shortest[0].v1 = v1;
11275                                                         shortest[0].v2 = v2;
11276                                                 }
11277                                                 else if (shortest[1].length2 > l || i == 1)
11278                                                 {
11279                                                         shortest[1].length2 = l;
11280                                                         shortest[1].v1 = v1;
11281                                                         shortest[1].v2 = v2;
11282                                                 }
11283                                         }
11284                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11285                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11286                                         // this calculates the right vector from the shortest edge
11287                                         // and the up vector from the edge midpoints
11288                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11289                                         VectorNormalize(right);
11290                                         VectorSubtract(end, start, up);
11291                                         VectorNormalize(up);
11292                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11293                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11294                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11295                                         VectorNegate(forward, forward);
11296                                         VectorReflect(forward, 0, up, forward);
11297                                         VectorNormalize(forward);
11298                                         CrossProduct(up, forward, newright);
11299                                         VectorNormalize(newright);
11300                                         // rotate the quad around the up axis vector, this is made
11301                                         // especially easy by the fact we know the quad is flat,
11302                                         // so we only have to subtract the center position and
11303                                         // measure distance along the right vector, and then
11304                                         // multiply that by the newright vector and add back the
11305                                         // center position
11306                                         // we also need to subtract the old position to undo the
11307                                         // displacement from the center, which we do with a
11308                                         // DotProduct, the subtraction/addition of center is also
11309                                         // optimized into DotProducts here
11310                                         l = DotProduct(right, center);
11311                                         for (i = 0;i < 4;i++)
11312                                         {
11313                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11314                                                 f = DotProduct(right, v1) - l;
11315                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
11316                                         }
11317                                 }
11318                         }
11319                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11320                         {
11321 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11322 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
11323 //                              rsurface.batchnormal3f_bufferoffset = 0;
11324                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11325                         }
11326                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11327                         {
11328 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11329 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11330 //                              rsurface.batchsvector3f_bufferoffset = 0;
11331 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11332 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11333 //                              rsurface.batchtvector3f_bufferoffset = 0;
11334                                 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);
11335                         }
11336                         break;
11337                 case Q3DEFORM_NORMAL:
11338                         // deform the normals to make reflections wavey
11339                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11340                         rsurface.batchnormal3f_vertexbuffer = NULL;
11341                         rsurface.batchnormal3f_bufferoffset = 0;
11342                         for (j = 0;j < batchnumvertices;j++)
11343                         {
11344                                 float vertex[3];
11345                                 float *normal = rsurface.batchnormal3f + 3*j;
11346                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11347                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11348                                 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]);
11349                                 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]);
11350                                 VectorNormalize(normal);
11351                         }
11352                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11353                         {
11354 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11355 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11356 //                              rsurface.batchsvector3f_bufferoffset = 0;
11357 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11358 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11359 //                              rsurface.batchtvector3f_bufferoffset = 0;
11360                                 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);
11361                         }
11362                         break;
11363                 case Q3DEFORM_WAVE:
11364                         // deform vertex array to make wavey water and flags and such
11365                         waveparms[0] = deform->waveparms[0];
11366                         waveparms[1] = deform->waveparms[1];
11367                         waveparms[2] = deform->waveparms[2];
11368                         waveparms[3] = deform->waveparms[3];
11369                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11370                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11371                         // this is how a divisor of vertex influence on deformation
11372                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11373                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11374 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11375 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11376 //                      rsurface.batchvertex3f_bufferoffset = 0;
11377 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11378 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11379 //                      rsurface.batchnormal3f_bufferoffset = 0;
11380                         for (j = 0;j < batchnumvertices;j++)
11381                         {
11382                                 // if the wavefunc depends on time, evaluate it per-vertex
11383                                 if (waveparms[3])
11384                                 {
11385                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11386                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11387                                 }
11388                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11389                         }
11390                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11391                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11392                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11393                         {
11394 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11395 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11396 //                              rsurface.batchsvector3f_bufferoffset = 0;
11397 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11398 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11399 //                              rsurface.batchtvector3f_bufferoffset = 0;
11400                                 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);
11401                         }
11402                         break;
11403                 case Q3DEFORM_BULGE:
11404                         // deform vertex array to make the surface have moving bulges
11405 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11406 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11407 //                      rsurface.batchvertex3f_bufferoffset = 0;
11408 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11409 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11410 //                      rsurface.batchnormal3f_bufferoffset = 0;
11411                         for (j = 0;j < batchnumvertices;j++)
11412                         {
11413                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11414                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11415                         }
11416                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11417                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11418                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11419                         {
11420 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11421 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11422 //                              rsurface.batchsvector3f_bufferoffset = 0;
11423 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11424 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11425 //                              rsurface.batchtvector3f_bufferoffset = 0;
11426                                 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);
11427                         }
11428                         break;
11429                 case Q3DEFORM_MOVE:
11430                         // deform vertex array
11431                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11432                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11433                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11434                         VectorScale(deform->parms, scale, waveparms);
11435 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11436 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11437 //                      rsurface.batchvertex3f_bufferoffset = 0;
11438                         for (j = 0;j < batchnumvertices;j++)
11439                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
11440                         break;
11441                 }
11442         }
11443
11444         // generate texcoords based on the chosen texcoord source
11445         switch(rsurface.texture->tcgen.tcgen)
11446         {
11447         default:
11448         case Q3TCGEN_TEXTURE:
11449                 break;
11450         case Q3TCGEN_LIGHTMAP:
11451 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11452 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11453 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11454                 if (rsurface.batchtexcoordlightmap2f)
11455                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
11456                 break;
11457         case Q3TCGEN_VECTOR:
11458 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11459 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11460 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11461                 for (j = 0;j < batchnumvertices;j++)
11462                 {
11463                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11464                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11465                 }
11466                 break;
11467         case Q3TCGEN_ENVIRONMENT:
11468                 // make environment reflections using a spheremap
11469                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11470                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11471                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11472                 for (j = 0;j < batchnumvertices;j++)
11473                 {
11474                         // identical to Q3A's method, but executed in worldspace so
11475                         // carried models can be shiny too
11476
11477                         float viewer[3], d, reflected[3], worldreflected[3];
11478
11479                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11480                         // VectorNormalize(viewer);
11481
11482                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11483
11484                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11485                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11486                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11487                         // note: this is proportinal to viewer, so we can normalize later
11488
11489                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11490                         VectorNormalize(worldreflected);
11491
11492                         // note: this sphere map only uses world x and z!
11493                         // so positive and negative y will LOOK THE SAME.
11494                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11495                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11496                 }
11497                 break;
11498         }
11499         // the only tcmod that needs software vertex processing is turbulent, so
11500         // check for it here and apply the changes if needed
11501         // and we only support that as the first one
11502         // (handling a mixture of turbulent and other tcmods would be problematic
11503         //  without punting it entirely to a software path)
11504         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11505         {
11506                 amplitude = rsurface.texture->tcmods[0].parms[1];
11507                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11508 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11509 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11510 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11511                 for (j = 0;j < batchnumvertices;j++)
11512                 {
11513                         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);
11514                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11515                 }
11516         }
11517
11518         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11519         {
11520                 // convert the modified arrays to vertex structs
11521 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11522 //              rsurface.batchvertexmeshbuffer = NULL;
11523                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11524                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11525                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11526                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11527                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11528                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11529                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11530                 {
11531                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11532                         {
11533                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11534                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11535                         }
11536                 }
11537                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11538                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11539                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
11540                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11541                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11542                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11543                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11544                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11545                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11546         }
11547 }
11548
11549 void RSurf_DrawBatch(void)
11550 {
11551         // sometimes a zero triangle surface (usually a degenerate patch) makes it
11552         // through the pipeline, killing it earlier in the pipeline would have
11553         // per-surface overhead rather than per-batch overhead, so it's best to
11554         // reject it here, before it hits glDraw.
11555         if (rsurface.batchnumtriangles == 0)
11556                 return;
11557 #if 0
11558         // batch debugging code
11559         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
11560         {
11561                 int i;
11562                 int j;
11563                 int c;
11564                 const int *e;
11565                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
11566                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
11567                 {
11568                         c = e[i];
11569                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
11570                         {
11571                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
11572                                 {
11573                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
11574                                                 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);
11575                                         break;
11576                                 }
11577                         }
11578                 }
11579         }
11580 #endif
11581         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);
11582 }
11583
11584 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11585 {
11586         // pick the closest matching water plane
11587         int planeindex, vertexindex, bestplaneindex = -1;
11588         float d, bestd;
11589         vec3_t vert;
11590         const float *v;
11591         r_waterstate_waterplane_t *p;
11592         qboolean prepared = false;
11593         bestd = 0;
11594         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11595         {
11596                 if(p->camera_entity != rsurface.texture->camera_entity)
11597                         continue;
11598                 d = 0;
11599                 if(!prepared)
11600                 {
11601                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11602                         prepared = true;
11603                         if(rsurface.batchnumvertices == 0)
11604                                 break;
11605                 }
11606                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11607                 {
11608                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
11609                         d += fabs(PlaneDiff(vert, &p->plane));
11610                 }
11611                 if (bestd > d || bestplaneindex < 0)
11612                 {
11613                         bestd = d;
11614                         bestplaneindex = planeindex;
11615                 }
11616         }
11617         return bestplaneindex;
11618         // NOTE: this MAY return a totally unrelated water plane; we can ignore
11619         // this situation though, as it might be better to render single larger
11620         // batches with useless stuff (backface culled for example) than to
11621         // render multiple smaller batches
11622 }
11623
11624 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11625 {
11626         int i;
11627         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11628         rsurface.passcolor4f_vertexbuffer = 0;
11629         rsurface.passcolor4f_bufferoffset = 0;
11630         for (i = 0;i < rsurface.batchnumvertices;i++)
11631                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11632 }
11633
11634 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11635 {
11636         int i;
11637         float f;
11638         const float *v;
11639         const float *c;
11640         float *c2;
11641         if (rsurface.passcolor4f)
11642         {
11643                 // generate color arrays
11644                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11645                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11646                 rsurface.passcolor4f_vertexbuffer = 0;
11647                 rsurface.passcolor4f_bufferoffset = 0;
11648                 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)
11649                 {
11650                         f = RSurf_FogVertex(v);
11651                         c2[0] = c[0] * f;
11652                         c2[1] = c[1] * f;
11653                         c2[2] = c[2] * f;
11654                         c2[3] = c[3];
11655                 }
11656         }
11657         else
11658         {
11659                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11660                 rsurface.passcolor4f_vertexbuffer = 0;
11661                 rsurface.passcolor4f_bufferoffset = 0;
11662                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11663                 {
11664                         f = RSurf_FogVertex(v);
11665                         c2[0] = f;
11666                         c2[1] = f;
11667                         c2[2] = f;
11668                         c2[3] = 1;
11669                 }
11670         }
11671 }
11672
11673 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11674 {
11675         int i;
11676         float f;
11677         const float *v;
11678         const float *c;
11679         float *c2;
11680         if (!rsurface.passcolor4f)
11681                 return;
11682         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11683         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11684         rsurface.passcolor4f_vertexbuffer = 0;
11685         rsurface.passcolor4f_bufferoffset = 0;
11686         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)
11687         {
11688                 f = RSurf_FogVertex(v);
11689                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11690                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11691                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11692                 c2[3] = c[3];
11693         }
11694 }
11695
11696 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11697 {
11698         int i;
11699         const float *c;
11700         float *c2;
11701         if (!rsurface.passcolor4f)
11702                 return;
11703         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11704         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11705         rsurface.passcolor4f_vertexbuffer = 0;
11706         rsurface.passcolor4f_bufferoffset = 0;
11707         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11708         {
11709                 c2[0] = c[0] * r;
11710                 c2[1] = c[1] * g;
11711                 c2[2] = c[2] * b;
11712                 c2[3] = c[3] * a;
11713         }
11714 }
11715
11716 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
11717 {
11718         int i;
11719         const float *c;
11720         float *c2;
11721         if (!rsurface.passcolor4f)
11722                 return;
11723         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11724         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11725         rsurface.passcolor4f_vertexbuffer = 0;
11726         rsurface.passcolor4f_bufferoffset = 0;
11727         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11728         {
11729                 c2[0] = c[0] + r_refdef.scene.ambient;
11730                 c2[1] = c[1] + r_refdef.scene.ambient;
11731                 c2[2] = c[2] + r_refdef.scene.ambient;
11732                 c2[3] = c[3];
11733         }
11734 }
11735
11736 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11737 {
11738         // TODO: optimize
11739         rsurface.passcolor4f = NULL;
11740         rsurface.passcolor4f_vertexbuffer = 0;
11741         rsurface.passcolor4f_bufferoffset = 0;
11742         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11743         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11744         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11745         GL_Color(r, g, b, a);
11746         R_Mesh_TexBind(0, rsurface.lightmaptexture);
11747         RSurf_DrawBatch();
11748 }
11749
11750 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11751 {
11752         // TODO: optimize applyfog && applycolor case
11753         // just apply fog if necessary, and tint the fog color array if necessary
11754         rsurface.passcolor4f = NULL;
11755         rsurface.passcolor4f_vertexbuffer = 0;
11756         rsurface.passcolor4f_bufferoffset = 0;
11757         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11758         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11759         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11760         GL_Color(r, g, b, a);
11761         RSurf_DrawBatch();
11762 }
11763
11764 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11765 {
11766         // TODO: optimize
11767         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11768         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11769         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11770         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11771         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11772         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11773         GL_Color(r, g, b, a);
11774         RSurf_DrawBatch();
11775 }
11776
11777 static void RSurf_DrawBatch_GL11_ClampColor(void)
11778 {
11779         int i;
11780         const float *c1;
11781         float *c2;
11782         if (!rsurface.passcolor4f)
11783                 return;
11784         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
11785         {
11786                 c2[0] = bound(0.0f, c1[0], 1.0f);
11787                 c2[1] = bound(0.0f, c1[1], 1.0f);
11788                 c2[2] = bound(0.0f, c1[2], 1.0f);
11789                 c2[3] = bound(0.0f, c1[3], 1.0f);
11790         }
11791 }
11792
11793 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
11794 {
11795         int i;
11796         float f;
11797         const float *v;
11798         const float *n;
11799         float *c;
11800         //vec3_t eyedir;
11801
11802         // fake shading
11803         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11804         rsurface.passcolor4f_vertexbuffer = 0;
11805         rsurface.passcolor4f_bufferoffset = 0;
11806         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)
11807         {
11808                 f = -DotProduct(r_refdef.view.forward, n);
11809                 f = max(0, f);
11810                 f = f * 0.85 + 0.15; // work around so stuff won't get black
11811                 f *= r_refdef.lightmapintensity;
11812                 Vector4Set(c, f, f, f, 1);
11813         }
11814 }
11815
11816 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11817 {
11818         RSurf_DrawBatch_GL11_ApplyFakeLight();
11819         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11820         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11821         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11822         GL_Color(r, g, b, a);
11823         RSurf_DrawBatch();
11824 }
11825
11826 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
11827 {
11828         int i;
11829         float f;
11830         float alpha;
11831         const float *v;
11832         const float *n;
11833         float *c;
11834         vec3_t ambientcolor;
11835         vec3_t diffusecolor;
11836         vec3_t lightdir;
11837         // TODO: optimize
11838         // model lighting
11839         VectorCopy(rsurface.modellight_lightdir, lightdir);
11840         f = 0.5f * r_refdef.lightmapintensity;
11841         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
11842         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
11843         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
11844         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
11845         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
11846         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
11847         alpha = *a;
11848         if (VectorLength2(diffusecolor) > 0)
11849         {
11850                 // q3-style directional shading
11851                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11852                 rsurface.passcolor4f_vertexbuffer = 0;
11853                 rsurface.passcolor4f_bufferoffset = 0;
11854                 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)
11855                 {
11856                         if ((f = DotProduct(n, lightdir)) > 0)
11857                                 VectorMA(ambientcolor, f, diffusecolor, c);
11858                         else
11859                                 VectorCopy(ambientcolor, c);
11860                         c[3] = alpha;
11861                 }
11862                 *r = 1;
11863                 *g = 1;
11864                 *b = 1;
11865                 *a = 1;
11866                 *applycolor = false;
11867         }
11868         else
11869         {
11870                 *r = ambientcolor[0];
11871                 *g = ambientcolor[1];
11872                 *b = ambientcolor[2];
11873                 rsurface.passcolor4f = NULL;
11874                 rsurface.passcolor4f_vertexbuffer = 0;
11875                 rsurface.passcolor4f_bufferoffset = 0;
11876         }
11877 }
11878
11879 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11880 {
11881         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
11882         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11883         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11884         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11885         GL_Color(r, g, b, a);
11886         RSurf_DrawBatch();
11887 }
11888
11889 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
11890 {
11891         int i;
11892         float f;
11893         const float *v;
11894         float *c;
11895         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
11896         {
11897                 f = 1 - RSurf_FogVertex(v);
11898                 c[0] = r;
11899                 c[1] = g;
11900                 c[2] = b;
11901                 c[3] = f * a;
11902         }
11903 }
11904
11905 void RSurf_SetupDepthAndCulling(void)
11906 {
11907         // submodels are biased to avoid z-fighting with world surfaces that they
11908         // may be exactly overlapping (avoids z-fighting artifacts on certain
11909         // doors and things in Quake maps)
11910         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
11911         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
11912         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
11913         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11914 }
11915
11916 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11917 {
11918         // transparent sky would be ridiculous
11919         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11920                 return;
11921         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11922         skyrenderlater = true;
11923         RSurf_SetupDepthAndCulling();
11924         GL_DepthMask(true);
11925         // LordHavoc: HalfLife maps have freaky skypolys so don't use
11926         // skymasking on them, and Quake3 never did sky masking (unlike
11927         // software Quake and software Quake2), so disable the sky masking
11928         // in Quake3 maps as it causes problems with q3map2 sky tricks,
11929         // and skymasking also looks very bad when noclipping outside the
11930         // level, so don't use it then either.
11931         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
11932         {
11933                 R_Mesh_ResetTextureState();
11934                 if (skyrendermasked)
11935                 {
11936                         R_SetupShader_DepthOrShadow();
11937                         // depth-only (masking)
11938                         GL_ColorMask(0,0,0,0);
11939                         // just to make sure that braindead drivers don't draw
11940                         // anything despite that colormask...
11941                         GL_BlendFunc(GL_ZERO, GL_ONE);
11942                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11943                         if (rsurface.batchvertex3fbuffer)
11944                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
11945                         else
11946                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
11947                 }
11948                 else
11949                 {
11950                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11951                         // fog sky
11952                         GL_BlendFunc(GL_ONE, GL_ZERO);
11953                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11954                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
11955                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11956                 }
11957                 RSurf_DrawBatch();
11958                 if (skyrendermasked)
11959                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11960         }
11961         R_Mesh_ResetTextureState();
11962         GL_Color(1, 1, 1, 1);
11963 }
11964
11965 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
11966 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
11967 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11968 {
11969         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
11970                 return;
11971         if (prepass)
11972         {
11973                 // render screenspace normalmap to texture
11974                 GL_DepthMask(true);
11975                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
11976                 RSurf_DrawBatch();
11977                 return;
11978         }
11979
11980         // bind lightmap texture
11981
11982         // water/refraction/reflection/camera surfaces have to be handled specially
11983         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
11984         {
11985                 int start, end, startplaneindex;
11986                 for (start = 0;start < texturenumsurfaces;start = end)
11987                 {
11988                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
11989                         if(startplaneindex < 0)
11990                         {
11991                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
11992                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
11993                                 end = start + 1;
11994                                 continue;
11995                         }
11996                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
11997                                 ;
11998                         // now that we have a batch using the same planeindex, render it
11999                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12000                         {
12001                                 // render water or distortion background
12002                                 GL_DepthMask(true);
12003                                 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));
12004                                 RSurf_DrawBatch();
12005                                 // blend surface on top
12006                                 GL_DepthMask(false);
12007                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12008                                 RSurf_DrawBatch();
12009                         }
12010                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12011                         {
12012                                 // render surface with reflection texture as input
12013                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12014                                 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));
12015                                 RSurf_DrawBatch();
12016                         }
12017                 }
12018                 return;
12019         }
12020
12021         // render surface batch normally
12022         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12023         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12024         RSurf_DrawBatch();
12025 }
12026
12027 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12028 {
12029         // OpenGL 1.3 path - anything not completely ancient
12030         qboolean applycolor;
12031         qboolean applyfog;
12032         int layerindex;
12033         const texturelayer_t *layer;
12034         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);
12035         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12036
12037         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12038         {
12039                 vec4_t layercolor;
12040                 int layertexrgbscale;
12041                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12042                 {
12043                         if (layerindex == 0)
12044                                 GL_AlphaTest(true);
12045                         else
12046                         {
12047                                 GL_AlphaTest(false);
12048                                 GL_DepthFunc(GL_EQUAL);
12049                         }
12050                 }
12051                 GL_DepthMask(layer->depthmask && writedepth);
12052                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12053                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12054                 {
12055                         layertexrgbscale = 4;
12056                         VectorScale(layer->color, 0.25f, layercolor);
12057                 }
12058                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12059                 {
12060                         layertexrgbscale = 2;
12061                         VectorScale(layer->color, 0.5f, layercolor);
12062                 }
12063                 else
12064                 {
12065                         layertexrgbscale = 1;
12066                         VectorScale(layer->color, 1.0f, layercolor);
12067                 }
12068                 layercolor[3] = layer->color[3];
12069                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12070                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12071                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12072                 switch (layer->type)
12073                 {
12074                 case TEXTURELAYERTYPE_LITTEXTURE:
12075                         // single-pass lightmapped texture with 2x rgbscale
12076                         R_Mesh_TexBind(0, r_texture_white);
12077                         R_Mesh_TexMatrix(0, NULL);
12078                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12079                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12080                         R_Mesh_TexBind(1, layer->texture);
12081                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12082                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12083                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12084                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12085                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12086                         else if (FAKELIGHT_ENABLED)
12087                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12088                         else if (rsurface.uselightmaptexture)
12089                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12090                         else
12091                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12092                         break;
12093                 case TEXTURELAYERTYPE_TEXTURE:
12094                         // singletexture unlit texture with transparency support
12095                         R_Mesh_TexBind(0, layer->texture);
12096                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12097                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12098                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12099                         R_Mesh_TexBind(1, 0);
12100                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12101                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12102                         break;
12103                 case TEXTURELAYERTYPE_FOG:
12104                         // singletexture fogging
12105                         if (layer->texture)
12106                         {
12107                                 R_Mesh_TexBind(0, layer->texture);
12108                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12109                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12110                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12111                         }
12112                         else
12113                         {
12114                                 R_Mesh_TexBind(0, 0);
12115                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12116                         }
12117                         R_Mesh_TexBind(1, 0);
12118                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12119                         // generate a color array for the fog pass
12120                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12121                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12122                         RSurf_DrawBatch();
12123                         break;
12124                 default:
12125                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12126                 }
12127         }
12128         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12129         {
12130                 GL_DepthFunc(GL_LEQUAL);
12131                 GL_AlphaTest(false);
12132         }
12133 }
12134
12135 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12136 {
12137         // OpenGL 1.1 - crusty old voodoo path
12138         qboolean applyfog;
12139         int layerindex;
12140         const texturelayer_t *layer;
12141         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);
12142         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12143
12144         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12145         {
12146                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12147                 {
12148                         if (layerindex == 0)
12149                                 GL_AlphaTest(true);
12150                         else
12151                         {
12152                                 GL_AlphaTest(false);
12153                                 GL_DepthFunc(GL_EQUAL);
12154                         }
12155                 }
12156                 GL_DepthMask(layer->depthmask && writedepth);
12157                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12158                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12159                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12160                 switch (layer->type)
12161                 {
12162                 case TEXTURELAYERTYPE_LITTEXTURE:
12163                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12164                         {
12165                                 // two-pass lit texture with 2x rgbscale
12166                                 // first the lightmap pass
12167                                 R_Mesh_TexBind(0, r_texture_white);
12168                                 R_Mesh_TexMatrix(0, NULL);
12169                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12170                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12171                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12172                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12173                                 else if (FAKELIGHT_ENABLED)
12174                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12175                                 else if (rsurface.uselightmaptexture)
12176                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12177                                 else
12178                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12179                                 // then apply the texture to it
12180                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12181                                 R_Mesh_TexBind(0, layer->texture);
12182                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12183                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12184                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12185                                 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);
12186                         }
12187                         else
12188                         {
12189                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12190                                 R_Mesh_TexBind(0, layer->texture);
12191                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12192                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12193                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12194                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12195                                         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);
12196                                 else
12197                                         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);
12198                         }
12199                         break;
12200                 case TEXTURELAYERTYPE_TEXTURE:
12201                         // singletexture unlit texture with transparency support
12202                         R_Mesh_TexBind(0, layer->texture);
12203                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12204                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12205                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12206                         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);
12207                         break;
12208                 case TEXTURELAYERTYPE_FOG:
12209                         // singletexture fogging
12210                         if (layer->texture)
12211                         {
12212                                 R_Mesh_TexBind(0, layer->texture);
12213                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12214                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12215                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12216                         }
12217                         else
12218                         {
12219                                 R_Mesh_TexBind(0, 0);
12220                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12221                         }
12222                         // generate a color array for the fog pass
12223                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12224                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12225                         RSurf_DrawBatch();
12226                         break;
12227                 default:
12228                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12229                 }
12230         }
12231         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12232         {
12233                 GL_DepthFunc(GL_LEQUAL);
12234                 GL_AlphaTest(false);
12235         }
12236 }
12237
12238 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12239 {
12240         int vi;
12241         int j;
12242         r_vertexgeneric_t *batchvertex;
12243         float c[4];
12244
12245 //      R_Mesh_ResetTextureState();
12246         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12247
12248         if(rsurface.texture && rsurface.texture->currentskinframe)
12249         {
12250                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12251                 c[3] *= rsurface.texture->currentalpha;
12252         }
12253         else
12254         {
12255                 c[0] = 1;
12256                 c[1] = 0;
12257                 c[2] = 1;
12258                 c[3] = 1;
12259         }
12260
12261         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12262         {
12263                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12264                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12265                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12266         }
12267
12268         // brighten it up (as texture value 127 means "unlit")
12269         c[0] *= 2 * r_refdef.view.colorscale;
12270         c[1] *= 2 * r_refdef.view.colorscale;
12271         c[2] *= 2 * r_refdef.view.colorscale;
12272
12273         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12274                 c[3] *= r_wateralpha.value;
12275
12276         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12277         {
12278                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12279                 GL_DepthMask(false);
12280         }
12281         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12282         {
12283                 GL_BlendFunc(GL_ONE, GL_ONE);
12284                 GL_DepthMask(false);
12285         }
12286         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12287         {
12288                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12289                 GL_DepthMask(false);
12290         }
12291         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12292         {
12293                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12294                 GL_DepthMask(false);
12295         }
12296         else
12297         {
12298                 GL_BlendFunc(GL_ONE, GL_ZERO);
12299                 GL_DepthMask(writedepth);
12300         }
12301
12302         if (r_showsurfaces.integer == 3)
12303         {
12304                 rsurface.passcolor4f = NULL;
12305
12306                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12307                 {
12308                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12309
12310                         rsurface.passcolor4f = NULL;
12311                         rsurface.passcolor4f_vertexbuffer = 0;
12312                         rsurface.passcolor4f_bufferoffset = 0;
12313                 }
12314                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12315                 {
12316                         qboolean applycolor = true;
12317                         float one = 1.0;
12318
12319                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12320
12321                         r_refdef.lightmapintensity = 1;
12322                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12323                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12324                 }
12325                 else if (FAKELIGHT_ENABLED)
12326                 {
12327                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12328
12329                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
12330                         RSurf_DrawBatch_GL11_ApplyFakeLight();
12331                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12332                 }
12333                 else
12334                 {
12335                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12336
12337                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12338                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12339                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12340                 }
12341
12342                 if(!rsurface.passcolor4f)
12343                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12344
12345                 RSurf_DrawBatch_GL11_ApplyAmbient();
12346                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12347                 if(r_refdef.fogenabled)
12348                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12349                 RSurf_DrawBatch_GL11_ClampColor();
12350
12351                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12352                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12353                 RSurf_DrawBatch();
12354         }
12355         else if (!r_refdef.view.showdebug)
12356         {
12357                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12358                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12359                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12360                 {
12361                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12362                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12363                 }
12364                 R_Mesh_PrepareVertices_Generic_Unlock();
12365                 RSurf_DrawBatch();
12366         }
12367         else if (r_showsurfaces.integer == 4)
12368         {
12369                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12370                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12371                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12372                 {
12373                         unsigned char c = vi << 3;
12374                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12375                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12376                 }
12377                 R_Mesh_PrepareVertices_Generic_Unlock();
12378                 RSurf_DrawBatch();
12379         }
12380         else if (r_showsurfaces.integer == 2)
12381         {
12382                 const int *e;
12383                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12384                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12385                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12386                 {
12387                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12388                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12389                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12390                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12391                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12392                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12393                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12394                 }
12395                 R_Mesh_PrepareVertices_Generic_Unlock();
12396                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12397         }
12398         else
12399         {
12400                 int texturesurfaceindex;
12401                 int k;
12402                 const msurface_t *surface;
12403                 unsigned char surfacecolor4ub[4];
12404                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12405                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12406                 vi = 0;
12407                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12408                 {
12409                         surface = texturesurfacelist[texturesurfaceindex];
12410                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12411                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12412                         for (j = 0;j < surface->num_vertices;j++)
12413                         {
12414                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12415                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12416                                 vi++;
12417                         }
12418                 }
12419                 R_Mesh_PrepareVertices_Generic_Unlock();
12420                 RSurf_DrawBatch();
12421         }
12422 }
12423
12424 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12425 {
12426         CHECKGLERROR
12427         RSurf_SetupDepthAndCulling();
12428         if (r_showsurfaces.integer)
12429         {
12430                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12431                 return;
12432         }
12433         switch (vid.renderpath)
12434         {
12435         case RENDERPATH_GL20:
12436         case RENDERPATH_D3D9:
12437         case RENDERPATH_D3D10:
12438         case RENDERPATH_D3D11:
12439         case RENDERPATH_SOFT:
12440         case RENDERPATH_GLES2:
12441                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12442                 break;
12443         case RENDERPATH_GL13:
12444                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12445                 break;
12446         case RENDERPATH_GL11:
12447                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12448                 break;
12449         }
12450         CHECKGLERROR
12451 }
12452
12453 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12454 {
12455         CHECKGLERROR
12456         RSurf_SetupDepthAndCulling();
12457         if (r_showsurfaces.integer)
12458         {
12459                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12460                 return;
12461         }
12462         switch (vid.renderpath)
12463         {
12464         case RENDERPATH_GL20:
12465         case RENDERPATH_D3D9:
12466         case RENDERPATH_D3D10:
12467         case RENDERPATH_D3D11:
12468         case RENDERPATH_SOFT:
12469         case RENDERPATH_GLES2:
12470                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12471                 break;
12472         case RENDERPATH_GL13:
12473                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12474                 break;
12475         case RENDERPATH_GL11:
12476                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12477                 break;
12478         }
12479         CHECKGLERROR
12480 }
12481
12482 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12483 {
12484         int i, j;
12485         int texturenumsurfaces, endsurface;
12486         texture_t *texture;
12487         const msurface_t *surface;
12488 #define MAXBATCH_TRANSPARENTSURFACES 256
12489         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12490
12491         // if the model is static it doesn't matter what value we give for
12492         // wantnormals and wanttangents, so this logic uses only rules applicable
12493         // to a model, knowing that they are meaningless otherwise
12494         if (ent == r_refdef.scene.worldentity)
12495                 RSurf_ActiveWorldEntity();
12496         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12497                 RSurf_ActiveModelEntity(ent, false, false, false);
12498         else
12499         {
12500                 switch (vid.renderpath)
12501                 {
12502                 case RENDERPATH_GL20:
12503                 case RENDERPATH_D3D9:
12504                 case RENDERPATH_D3D10:
12505                 case RENDERPATH_D3D11:
12506                 case RENDERPATH_SOFT:
12507                 case RENDERPATH_GLES2:
12508                         RSurf_ActiveModelEntity(ent, true, true, false);
12509                         break;
12510                 case RENDERPATH_GL13:
12511                 case RENDERPATH_GL11:
12512                         RSurf_ActiveModelEntity(ent, true, false, false);
12513                         break;
12514                 }
12515         }
12516
12517         if (r_transparentdepthmasking.integer)
12518         {
12519                 qboolean setup = false;
12520                 for (i = 0;i < numsurfaces;i = j)
12521                 {
12522                         j = i + 1;
12523                         surface = rsurface.modelsurfaces + surfacelist[i];
12524                         texture = surface->texture;
12525                         rsurface.texture = R_GetCurrentTexture(texture);
12526                         rsurface.lightmaptexture = NULL;
12527                         rsurface.deluxemaptexture = NULL;
12528                         rsurface.uselightmaptexture = false;
12529                         // scan ahead until we find a different texture
12530                         endsurface = min(i + 1024, numsurfaces);
12531                         texturenumsurfaces = 0;
12532                         texturesurfacelist[texturenumsurfaces++] = surface;
12533                         for (;j < endsurface;j++)
12534                         {
12535                                 surface = rsurface.modelsurfaces + surfacelist[j];
12536                                 if (texture != surface->texture)
12537                                         break;
12538                                 texturesurfacelist[texturenumsurfaces++] = surface;
12539                         }
12540                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12541                                 continue;
12542                         // render the range of surfaces as depth
12543                         if (!setup)
12544                         {
12545                                 setup = true;
12546                                 GL_ColorMask(0,0,0,0);
12547                                 GL_Color(1,1,1,1);
12548                                 GL_DepthTest(true);
12549                                 GL_BlendFunc(GL_ONE, GL_ZERO);
12550                                 GL_DepthMask(true);
12551 //                              R_Mesh_ResetTextureState();
12552                                 R_SetupShader_DepthOrShadow();
12553                         }
12554                         RSurf_SetupDepthAndCulling();
12555                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12556                         if (rsurface.batchvertex3fbuffer)
12557                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12558                         else
12559                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12560                         RSurf_DrawBatch();
12561                 }
12562                 if (setup)
12563                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12564         }
12565
12566         for (i = 0;i < numsurfaces;i = j)
12567         {
12568                 j = i + 1;
12569                 surface = rsurface.modelsurfaces + surfacelist[i];
12570                 texture = surface->texture;
12571                 rsurface.texture = R_GetCurrentTexture(texture);
12572                 // scan ahead until we find a different texture
12573                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12574                 texturenumsurfaces = 0;
12575                 texturesurfacelist[texturenumsurfaces++] = surface;
12576                 if(FAKELIGHT_ENABLED)
12577                 {
12578                         rsurface.lightmaptexture = NULL;
12579                         rsurface.deluxemaptexture = NULL;
12580                         rsurface.uselightmaptexture = false;
12581                         for (;j < endsurface;j++)
12582                         {
12583                                 surface = rsurface.modelsurfaces + surfacelist[j];
12584                                 if (texture != surface->texture)
12585                                         break;
12586                                 texturesurfacelist[texturenumsurfaces++] = surface;
12587                         }
12588                 }
12589                 else
12590                 {
12591                         rsurface.lightmaptexture = surface->lightmaptexture;
12592                         rsurface.deluxemaptexture = surface->deluxemaptexture;
12593                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12594                         for (;j < endsurface;j++)
12595                         {
12596                                 surface = rsurface.modelsurfaces + surfacelist[j];
12597                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12598                                         break;
12599                                 texturesurfacelist[texturenumsurfaces++] = surface;
12600                         }
12601                 }
12602                 // render the range of surfaces
12603                 if (ent == r_refdef.scene.worldentity)
12604                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12605                 else
12606                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12607         }
12608         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12609 }
12610
12611 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12612 {
12613         // transparent surfaces get pushed off into the transparent queue
12614         int surfacelistindex;
12615         const msurface_t *surface;
12616         vec3_t tempcenter, center;
12617         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12618         {
12619                 surface = texturesurfacelist[surfacelistindex];
12620                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12621                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12622                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12623                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12624                 if (queueentity->transparent_offset) // transparent offset
12625                 {
12626                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12627                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12628                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12629                 }
12630                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12631         }
12632 }
12633
12634 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12635 {
12636         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12637                 return;
12638         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12639                 return;
12640         RSurf_SetupDepthAndCulling();
12641         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12642         if (rsurface.batchvertex3fbuffer)
12643                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12644         else
12645                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12646         RSurf_DrawBatch();
12647 }
12648
12649 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12650 {
12651         const entity_render_t *queueentity = r_refdef.scene.worldentity;
12652         CHECKGLERROR
12653         if (depthonly)
12654                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12655         else if (prepass)
12656         {
12657                 if (!rsurface.texture->currentnumlayers)
12658                         return;
12659                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12660                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12661                 else
12662                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12663         }
12664         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12665                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12666         else if (!rsurface.texture->currentnumlayers)
12667                 return;
12668         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12669         {
12670                 // in the deferred case, transparent surfaces were queued during prepass
12671                 if (!r_shadow_usingdeferredprepass)
12672                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12673         }
12674         else
12675         {
12676                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12677                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12678         }
12679         CHECKGLERROR
12680 }
12681
12682 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12683 {
12684         int i, j;
12685         texture_t *texture;
12686         R_FrameData_SetMark();
12687         // break the surface list down into batches by texture and use of lightmapping
12688         for (i = 0;i < numsurfaces;i = j)
12689         {
12690                 j = i + 1;
12691                 // texture is the base texture pointer, rsurface.texture is the
12692                 // current frame/skin the texture is directing us to use (for example
12693                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12694                 // use skin 1 instead)
12695                 texture = surfacelist[i]->texture;
12696                 rsurface.texture = R_GetCurrentTexture(texture);
12697                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12698                 {
12699                         // if this texture is not the kind we want, skip ahead to the next one
12700                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12701                                 ;
12702                         continue;
12703                 }
12704                 if(FAKELIGHT_ENABLED || depthonly || prepass)
12705                 {
12706                         rsurface.lightmaptexture = NULL;
12707                         rsurface.deluxemaptexture = NULL;
12708                         rsurface.uselightmaptexture = false;
12709                         // simply scan ahead until we find a different texture or lightmap state
12710                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12711                                 ;
12712                 }
12713                 else
12714                 {
12715                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12716                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12717                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12718                         // simply scan ahead until we find a different texture or lightmap state
12719                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12720                                 ;
12721                 }
12722                 // render the range of surfaces
12723                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12724         }
12725         R_FrameData_ReturnToMark();
12726 }
12727
12728 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12729 {
12730         CHECKGLERROR
12731         if (depthonly)
12732                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12733         else if (prepass)
12734         {
12735                 if (!rsurface.texture->currentnumlayers)
12736                         return;
12737                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12738                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12739                 else
12740                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12741         }
12742         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12743                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12744         else if (!rsurface.texture->currentnumlayers)
12745                 return;
12746         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12747         {
12748                 // in the deferred case, transparent surfaces were queued during prepass
12749                 if (!r_shadow_usingdeferredprepass)
12750                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12751         }
12752         else
12753         {
12754                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12755                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12756         }
12757         CHECKGLERROR
12758 }
12759
12760 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12761 {
12762         int i, j;
12763         texture_t *texture;
12764         R_FrameData_SetMark();
12765         // break the surface list down into batches by texture and use of lightmapping
12766         for (i = 0;i < numsurfaces;i = j)
12767         {
12768                 j = i + 1;
12769                 // texture is the base texture pointer, rsurface.texture is the
12770                 // current frame/skin the texture is directing us to use (for example
12771                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12772                 // use skin 1 instead)
12773                 texture = surfacelist[i]->texture;
12774                 rsurface.texture = R_GetCurrentTexture(texture);
12775                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12776                 {
12777                         // if this texture is not the kind we want, skip ahead to the next one
12778                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12779                                 ;
12780                         continue;
12781                 }
12782                 if(FAKELIGHT_ENABLED || depthonly || prepass)
12783                 {
12784                         rsurface.lightmaptexture = NULL;
12785                         rsurface.deluxemaptexture = NULL;
12786                         rsurface.uselightmaptexture = false;
12787                         // simply scan ahead until we find a different texture or lightmap state
12788                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12789                                 ;
12790                 }
12791                 else
12792                 {
12793                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12794                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12795                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12796                         // simply scan ahead until we find a different texture or lightmap state
12797                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12798                                 ;
12799                 }
12800                 // render the range of surfaces
12801                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12802         }
12803         R_FrameData_ReturnToMark();
12804 }
12805
12806 float locboxvertex3f[6*4*3] =
12807 {
12808         1,0,1, 1,0,0, 1,1,0, 1,1,1,
12809         0,1,1, 0,1,0, 0,0,0, 0,0,1,
12810         1,1,1, 1,1,0, 0,1,0, 0,1,1,
12811         0,0,1, 0,0,0, 1,0,0, 1,0,1,
12812         0,0,1, 1,0,1, 1,1,1, 0,1,1,
12813         1,0,0, 0,0,0, 0,1,0, 1,1,0
12814 };
12815
12816 unsigned short locboxelements[6*2*3] =
12817 {
12818          0, 1, 2, 0, 2, 3,
12819          4, 5, 6, 4, 6, 7,
12820          8, 9,10, 8,10,11,
12821         12,13,14, 12,14,15,
12822         16,17,18, 16,18,19,
12823         20,21,22, 20,22,23
12824 };
12825
12826 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12827 {
12828         int i, j;
12829         cl_locnode_t *loc = (cl_locnode_t *)ent;
12830         vec3_t mins, size;
12831         float vertex3f[6*4*3];
12832         CHECKGLERROR
12833         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12834         GL_DepthMask(false);
12835         GL_DepthRange(0, 1);
12836         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12837         GL_DepthTest(true);
12838         GL_CullFace(GL_NONE);
12839         R_EntityMatrix(&identitymatrix);
12840
12841 //      R_Mesh_ResetTextureState();
12842
12843         i = surfacelist[0];
12844         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12845                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12846                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12847                         surfacelist[0] < 0 ? 0.5f : 0.125f);
12848
12849         if (VectorCompare(loc->mins, loc->maxs))
12850         {
12851                 VectorSet(size, 2, 2, 2);
12852                 VectorMA(loc->mins, -0.5f, size, mins);
12853         }
12854         else
12855         {
12856                 VectorCopy(loc->mins, mins);
12857                 VectorSubtract(loc->maxs, loc->mins, size);
12858         }
12859
12860         for (i = 0;i < 6*4*3;)
12861                 for (j = 0;j < 3;j++, i++)
12862                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
12863
12864         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
12865         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12866         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
12867 }
12868
12869 void R_DrawLocs(void)
12870 {
12871         int index;
12872         cl_locnode_t *loc, *nearestloc;
12873         vec3_t center;
12874         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
12875         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
12876         {
12877                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
12878                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
12879         }
12880 }
12881
12882 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
12883 {
12884         if (decalsystem->decals)
12885                 Mem_Free(decalsystem->decals);
12886         memset(decalsystem, 0, sizeof(*decalsystem));
12887 }
12888
12889 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)
12890 {
12891         tridecal_t *decal;
12892         tridecal_t *decals;
12893         int i;
12894
12895         // expand or initialize the system
12896         if (decalsystem->maxdecals <= decalsystem->numdecals)
12897         {
12898                 decalsystem_t old = *decalsystem;
12899                 qboolean useshortelements;
12900                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
12901                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
12902                 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)));
12903                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
12904                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
12905                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
12906                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
12907                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
12908                 if (decalsystem->numdecals)
12909                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
12910                 if (old.decals)
12911                         Mem_Free(old.decals);
12912                 for (i = 0;i < decalsystem->maxdecals*3;i++)
12913                         decalsystem->element3i[i] = i;
12914                 if (useshortelements)
12915                         for (i = 0;i < decalsystem->maxdecals*3;i++)
12916                                 decalsystem->element3s[i] = i;
12917         }
12918
12919         // grab a decal and search for another free slot for the next one
12920         decals = decalsystem->decals;
12921         decal = decalsystem->decals + (i = decalsystem->freedecal++);
12922         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
12923                 ;
12924         decalsystem->freedecal = i;
12925         if (decalsystem->numdecals <= i)
12926                 decalsystem->numdecals = i + 1;
12927
12928         // initialize the decal
12929         decal->lived = 0;
12930         decal->triangleindex = triangleindex;
12931         decal->surfaceindex = surfaceindex;
12932         decal->decalsequence = decalsequence;
12933         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
12934         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
12935         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
12936         decal->color4ub[0][3] = 255;
12937         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
12938         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
12939         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
12940         decal->color4ub[1][3] = 255;
12941         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
12942         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
12943         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
12944         decal->color4ub[2][3] = 255;
12945         decal->vertex3f[0][0] = v0[0];
12946         decal->vertex3f[0][1] = v0[1];
12947         decal->vertex3f[0][2] = v0[2];
12948         decal->vertex3f[1][0] = v1[0];
12949         decal->vertex3f[1][1] = v1[1];
12950         decal->vertex3f[1][2] = v1[2];
12951         decal->vertex3f[2][0] = v2[0];
12952         decal->vertex3f[2][1] = v2[1];
12953         decal->vertex3f[2][2] = v2[2];
12954         decal->texcoord2f[0][0] = t0[0];
12955         decal->texcoord2f[0][1] = t0[1];
12956         decal->texcoord2f[1][0] = t1[0];
12957         decal->texcoord2f[1][1] = t1[1];
12958         decal->texcoord2f[2][0] = t2[0];
12959         decal->texcoord2f[2][1] = t2[1];
12960 }
12961
12962 extern cvar_t cl_decals_bias;
12963 extern cvar_t cl_decals_models;
12964 extern cvar_t cl_decals_newsystem_intensitymultiplier;
12965 // baseparms, parms, temps
12966 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)
12967 {
12968         int cornerindex;
12969         int index;
12970         float v[9][3];
12971         const float *vertex3f;
12972         int numpoints;
12973         float points[2][9][3];
12974         float temp[3];
12975         float tc[9][2];
12976         float f;
12977         float c[9][4];
12978         const int *e;
12979
12980         e = rsurface.modelelement3i + 3*triangleindex;
12981
12982         vertex3f = rsurface.modelvertex3f;
12983
12984         for (cornerindex = 0;cornerindex < 3;cornerindex++)
12985         {
12986                 index = 3*e[cornerindex];
12987                 VectorCopy(vertex3f + index, v[cornerindex]);
12988         }
12989         // cull backfaces
12990         //TriangleNormal(v[0], v[1], v[2], normal);
12991         //if (DotProduct(normal, localnormal) < 0.0f)
12992         //      continue;
12993         // clip by each of the box planes formed from the projection matrix
12994         // if anything survives, we emit the decal
12995         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]);
12996         if (numpoints < 3)
12997                 return;
12998         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]);
12999         if (numpoints < 3)
13000                 return;
13001         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]);
13002         if (numpoints < 3)
13003                 return;
13004         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]);
13005         if (numpoints < 3)
13006                 return;
13007         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]);
13008         if (numpoints < 3)
13009                 return;
13010         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]);
13011         if (numpoints < 3)
13012                 return;
13013         // some part of the triangle survived, so we have to accept it...
13014         if (dynamic)
13015         {
13016                 // dynamic always uses the original triangle
13017                 numpoints = 3;
13018                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13019                 {
13020                         index = 3*e[cornerindex];
13021                         VectorCopy(vertex3f + index, v[cornerindex]);
13022                 }
13023         }
13024         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13025         {
13026                 // convert vertex positions to texcoords
13027                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13028                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13029                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13030                 // calculate distance fade from the projection origin
13031                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13032                 f = bound(0.0f, f, 1.0f);
13033                 c[cornerindex][0] = r * f;
13034                 c[cornerindex][1] = g * f;
13035                 c[cornerindex][2] = b * f;
13036                 c[cornerindex][3] = 1.0f;
13037                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13038         }
13039         if (dynamic)
13040                 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);
13041         else
13042                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13043                         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);
13044 }
13045 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)
13046 {
13047         matrix4x4_t projection;
13048         decalsystem_t *decalsystem;
13049         qboolean dynamic;
13050         dp_model_t *model;
13051         const msurface_t *surface;
13052         const msurface_t *surfaces;
13053         const int *surfacelist;
13054         const texture_t *texture;
13055         int numtriangles;
13056         int numsurfacelist;
13057         int surfacelistindex;
13058         int surfaceindex;
13059         int triangleindex;
13060         float localorigin[3];
13061         float localnormal[3];
13062         float localmins[3];
13063         float localmaxs[3];
13064         float localsize;
13065         //float normal[3];
13066         float planes[6][4];
13067         float angles[3];
13068         bih_t *bih;
13069         int bih_triangles_count;
13070         int bih_triangles[256];
13071         int bih_surfaces[256];
13072
13073         decalsystem = &ent->decalsystem;
13074         model = ent->model;
13075         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13076         {
13077                 R_DecalSystem_Reset(&ent->decalsystem);
13078                 return;
13079         }
13080
13081         if (!model->brush.data_leafs && !cl_decals_models.integer)
13082         {
13083                 if (decalsystem->model)
13084                         R_DecalSystem_Reset(decalsystem);
13085                 return;
13086         }
13087
13088         if (decalsystem->model != model)
13089                 R_DecalSystem_Reset(decalsystem);
13090         decalsystem->model = model;
13091
13092         RSurf_ActiveModelEntity(ent, false, false, false);
13093
13094         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13095         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13096         VectorNormalize(localnormal);
13097         localsize = worldsize*rsurface.inversematrixscale;
13098         localmins[0] = localorigin[0] - localsize;
13099         localmins[1] = localorigin[1] - localsize;
13100         localmins[2] = localorigin[2] - localsize;
13101         localmaxs[0] = localorigin[0] + localsize;
13102         localmaxs[1] = localorigin[1] + localsize;
13103         localmaxs[2] = localorigin[2] + localsize;
13104
13105         //VectorCopy(localnormal, planes[4]);
13106         //VectorVectors(planes[4], planes[2], planes[0]);
13107         AnglesFromVectors(angles, localnormal, NULL, false);
13108         AngleVectors(angles, planes[0], planes[2], planes[4]);
13109         VectorNegate(planes[0], planes[1]);
13110         VectorNegate(planes[2], planes[3]);
13111         VectorNegate(planes[4], planes[5]);
13112         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13113         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13114         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13115         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13116         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13117         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13118
13119 #if 1
13120 // works
13121 {
13122         matrix4x4_t forwardprojection;
13123         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13124         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13125 }
13126 #else
13127 // broken
13128 {
13129         float projectionvector[4][3];
13130         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13131         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13132         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13133         projectionvector[0][0] = planes[0][0] * ilocalsize;
13134         projectionvector[0][1] = planes[1][0] * ilocalsize;
13135         projectionvector[0][2] = planes[2][0] * ilocalsize;
13136         projectionvector[1][0] = planes[0][1] * ilocalsize;
13137         projectionvector[1][1] = planes[1][1] * ilocalsize;
13138         projectionvector[1][2] = planes[2][1] * ilocalsize;
13139         projectionvector[2][0] = planes[0][2] * ilocalsize;
13140         projectionvector[2][1] = planes[1][2] * ilocalsize;
13141         projectionvector[2][2] = planes[2][2] * ilocalsize;
13142         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13143         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13144         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13145         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13146 }
13147 #endif
13148
13149         dynamic = model->surfmesh.isanimated;
13150         numsurfacelist = model->nummodelsurfaces;
13151         surfacelist = model->sortedmodelsurfaces;
13152         surfaces = model->data_surfaces;
13153
13154         bih = NULL;
13155         bih_triangles_count = -1;
13156         if(!dynamic)
13157         {
13158                 if(model->render_bih.numleafs)
13159                         bih = &model->render_bih;
13160                 else if(model->collision_bih.numleafs)
13161                         bih = &model->collision_bih;
13162         }
13163         if(bih)
13164                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13165         if(bih_triangles_count == 0)
13166                 return;
13167         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13168                 return;
13169         if(bih_triangles_count > 0)
13170         {
13171                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13172                 {
13173                         surfaceindex = bih_surfaces[triangleindex];
13174                         surface = surfaces + surfaceindex;
13175                         texture = surface->texture;
13176                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13177                                 continue;
13178                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13179                                 continue;
13180                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13181                 }
13182         }
13183         else
13184         {
13185                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13186                 {
13187                         surfaceindex = surfacelist[surfacelistindex];
13188                         surface = surfaces + surfaceindex;
13189                         // check cull box first because it rejects more than any other check
13190                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13191                                 continue;
13192                         // skip transparent surfaces
13193                         texture = surface->texture;
13194                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13195                                 continue;
13196                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13197                                 continue;
13198                         numtriangles = surface->num_triangles;
13199                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13200                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13201                 }
13202         }
13203 }
13204
13205 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13206 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)
13207 {
13208         int renderentityindex;
13209         float worldmins[3];
13210         float worldmaxs[3];
13211         entity_render_t *ent;
13212
13213         if (!cl_decals_newsystem.integer)
13214                 return;
13215
13216         worldmins[0] = worldorigin[0] - worldsize;
13217         worldmins[1] = worldorigin[1] - worldsize;
13218         worldmins[2] = worldorigin[2] - worldsize;
13219         worldmaxs[0] = worldorigin[0] + worldsize;
13220         worldmaxs[1] = worldorigin[1] + worldsize;
13221         worldmaxs[2] = worldorigin[2] + worldsize;
13222
13223         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13224
13225         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13226         {
13227                 ent = r_refdef.scene.entities[renderentityindex];
13228                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13229                         continue;
13230
13231                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13232         }
13233 }
13234
13235 typedef struct r_decalsystem_splatqueue_s
13236 {
13237         vec3_t worldorigin;
13238         vec3_t worldnormal;
13239         float color[4];
13240         float tcrange[4];
13241         float worldsize;
13242         int decalsequence;
13243 }
13244 r_decalsystem_splatqueue_t;
13245
13246 int r_decalsystem_numqueued = 0;
13247 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13248
13249 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)
13250 {
13251         r_decalsystem_splatqueue_t *queue;
13252
13253         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13254                 return;
13255
13256         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13257         VectorCopy(worldorigin, queue->worldorigin);
13258         VectorCopy(worldnormal, queue->worldnormal);
13259         Vector4Set(queue->color, r, g, b, a);
13260         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13261         queue->worldsize = worldsize;
13262         queue->decalsequence = cl.decalsequence++;
13263 }
13264
13265 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13266 {
13267         int i;
13268         r_decalsystem_splatqueue_t *queue;
13269
13270         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13271                 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);
13272         r_decalsystem_numqueued = 0;
13273 }
13274
13275 extern cvar_t cl_decals_max;
13276 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13277 {
13278         int i;
13279         decalsystem_t *decalsystem = &ent->decalsystem;
13280         int numdecals;
13281         int killsequence;
13282         tridecal_t *decal;
13283         float frametime;
13284         float lifetime;
13285
13286         if (!decalsystem->numdecals)
13287                 return;
13288
13289         if (r_showsurfaces.integer)
13290                 return;
13291
13292         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13293         {
13294                 R_DecalSystem_Reset(decalsystem);
13295                 return;
13296         }
13297
13298         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13299         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13300
13301         if (decalsystem->lastupdatetime)
13302                 frametime = (cl.time - decalsystem->lastupdatetime);
13303         else
13304                 frametime = 0;
13305         decalsystem->lastupdatetime = cl.time;
13306         decal = decalsystem->decals;
13307         numdecals = decalsystem->numdecals;
13308
13309         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13310         {
13311                 if (decal->color4ub[0][3])
13312                 {
13313                         decal->lived += frametime;
13314                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13315                         {
13316                                 memset(decal, 0, sizeof(*decal));
13317                                 if (decalsystem->freedecal > i)
13318                                         decalsystem->freedecal = i;
13319                         }
13320                 }
13321         }
13322         decal = decalsystem->decals;
13323         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13324                 numdecals--;
13325
13326         // collapse the array by shuffling the tail decals into the gaps
13327         for (;;)
13328         {
13329                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13330                         decalsystem->freedecal++;
13331                 if (decalsystem->freedecal == numdecals)
13332                         break;
13333                 decal[decalsystem->freedecal] = decal[--numdecals];
13334         }
13335
13336         decalsystem->numdecals = numdecals;
13337
13338         if (numdecals <= 0)
13339         {
13340                 // if there are no decals left, reset decalsystem
13341                 R_DecalSystem_Reset(decalsystem);
13342         }
13343 }
13344
13345 extern skinframe_t *decalskinframe;
13346 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13347 {
13348         int i;
13349         decalsystem_t *decalsystem = &ent->decalsystem;
13350         int numdecals;
13351         tridecal_t *decal;
13352         float faderate;
13353         float alpha;
13354         float *v3f;
13355         float *c4f;
13356         float *t2f;
13357         const int *e;
13358         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13359         int numtris = 0;
13360
13361         numdecals = decalsystem->numdecals;
13362         if (!numdecals)
13363                 return;
13364
13365         if (r_showsurfaces.integer)
13366                 return;
13367
13368         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13369         {
13370                 R_DecalSystem_Reset(decalsystem);
13371                 return;
13372         }
13373
13374         // if the model is static it doesn't matter what value we give for
13375         // wantnormals and wanttangents, so this logic uses only rules applicable
13376         // to a model, knowing that they are meaningless otherwise
13377         if (ent == r_refdef.scene.worldentity)
13378                 RSurf_ActiveWorldEntity();
13379         else
13380                 RSurf_ActiveModelEntity(ent, false, false, false);
13381
13382         decalsystem->lastupdatetime = cl.time;
13383         decal = decalsystem->decals;
13384
13385         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13386
13387         // update vertex positions for animated models
13388         v3f = decalsystem->vertex3f;
13389         c4f = decalsystem->color4f;
13390         t2f = decalsystem->texcoord2f;
13391         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13392         {
13393                 if (!decal->color4ub[0][3])
13394                         continue;
13395
13396                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13397                         continue;
13398
13399                 // update color values for fading decals
13400                 if (decal->lived >= cl_decals_time.value)
13401                 {
13402                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13403                         alpha *= (1.0f/255.0f);
13404                 }
13405                 else
13406                         alpha = 1.0f/255.0f;
13407
13408                 c4f[ 0] = decal->color4ub[0][0] * alpha;
13409                 c4f[ 1] = decal->color4ub[0][1] * alpha;
13410                 c4f[ 2] = decal->color4ub[0][2] * alpha;
13411                 c4f[ 3] = 1;
13412                 c4f[ 4] = decal->color4ub[1][0] * alpha;
13413                 c4f[ 5] = decal->color4ub[1][1] * alpha;
13414                 c4f[ 6] = decal->color4ub[1][2] * alpha;
13415                 c4f[ 7] = 1;
13416                 c4f[ 8] = decal->color4ub[2][0] * alpha;
13417                 c4f[ 9] = decal->color4ub[2][1] * alpha;
13418                 c4f[10] = decal->color4ub[2][2] * alpha;
13419                 c4f[11] = 1;
13420
13421                 t2f[0] = decal->texcoord2f[0][0];
13422                 t2f[1] = decal->texcoord2f[0][1];
13423                 t2f[2] = decal->texcoord2f[1][0];
13424                 t2f[3] = decal->texcoord2f[1][1];
13425                 t2f[4] = decal->texcoord2f[2][0];
13426                 t2f[5] = decal->texcoord2f[2][1];
13427
13428                 // update vertex positions for animated models
13429                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13430                 {
13431                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13432                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
13433                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
13434                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
13435                 }
13436                 else
13437                 {
13438                         VectorCopy(decal->vertex3f[0], v3f);
13439                         VectorCopy(decal->vertex3f[1], v3f + 3);
13440                         VectorCopy(decal->vertex3f[2], v3f + 6);
13441                 }
13442
13443                 if (r_refdef.fogenabled)
13444                 {
13445                         alpha = RSurf_FogVertex(v3f);
13446                         VectorScale(c4f, alpha, c4f);
13447                         alpha = RSurf_FogVertex(v3f + 3);
13448                         VectorScale(c4f + 4, alpha, c4f + 4);
13449                         alpha = RSurf_FogVertex(v3f + 6);
13450                         VectorScale(c4f + 8, alpha, c4f + 8);
13451                 }
13452
13453                 v3f += 9;
13454                 c4f += 12;
13455                 t2f += 6;
13456                 numtris++;
13457         }
13458
13459         if (numtris > 0)
13460         {
13461                 r_refdef.stats.drawndecals += numtris;
13462
13463                 // now render the decals all at once
13464                 // (this assumes they all use one particle font texture!)
13465                 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);
13466 //              R_Mesh_ResetTextureState();
13467                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13468                 GL_DepthMask(false);
13469                 GL_DepthRange(0, 1);
13470                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13471                 GL_DepthTest(true);
13472                 GL_CullFace(GL_NONE);
13473                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13474                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13475                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13476         }
13477 }
13478
13479 static void R_DrawModelDecals(void)
13480 {
13481         int i, numdecals;
13482
13483         // fade faster when there are too many decals
13484         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13485         for (i = 0;i < r_refdef.scene.numentities;i++)
13486                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13487
13488         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13489         for (i = 0;i < r_refdef.scene.numentities;i++)
13490                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13491                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13492
13493         R_DecalSystem_ApplySplatEntitiesQueue();
13494
13495         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13496         for (i = 0;i < r_refdef.scene.numentities;i++)
13497                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13498
13499         r_refdef.stats.totaldecals += numdecals;
13500
13501         if (r_showsurfaces.integer)
13502                 return;
13503
13504         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13505
13506         for (i = 0;i < r_refdef.scene.numentities;i++)
13507         {
13508                 if (!r_refdef.viewcache.entityvisible[i])
13509                         continue;
13510                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13511                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13512         }
13513 }
13514
13515 extern cvar_t mod_collision_bih;
13516 void R_DrawDebugModel(void)
13517 {
13518         entity_render_t *ent = rsurface.entity;
13519         int i, j, k, l, flagsmask;
13520         const msurface_t *surface;
13521         dp_model_t *model = ent->model;
13522         vec3_t v;
13523
13524         switch(vid.renderpath)
13525         {
13526         case RENDERPATH_GL11:
13527         case RENDERPATH_GL13:
13528         case RENDERPATH_GL20:
13529                 break;
13530         case RENDERPATH_D3D9:
13531                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13532                 return;
13533         case RENDERPATH_D3D10:
13534                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13535                 return;
13536         case RENDERPATH_D3D11:
13537                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13538                 return;
13539         case RENDERPATH_SOFT:
13540                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13541                 return;
13542         case RENDERPATH_GLES2:
13543                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13544                 return;
13545         }
13546
13547         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13548
13549 //      R_Mesh_ResetTextureState();
13550         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13551         GL_DepthRange(0, 1);
13552         GL_DepthTest(!r_showdisabledepthtest.integer);
13553         GL_DepthMask(false);
13554         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13555
13556         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13557         {
13558                 int triangleindex;
13559                 int bihleafindex;
13560                 qboolean cullbox = ent == r_refdef.scene.worldentity;
13561                 const q3mbrush_t *brush;
13562                 const bih_t *bih = &model->collision_bih;
13563                 const bih_leaf_t *bihleaf;
13564                 float vertex3f[3][3];
13565                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13566                 cullbox = false;
13567                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13568                 {
13569                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13570                                 continue;
13571                         switch (bihleaf->type)
13572                         {
13573                         case BIH_BRUSH:
13574                                 brush = model->brush.data_brushes + bihleaf->itemindex;
13575                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
13576                                 {
13577                                         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);
13578                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13579                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13580                                 }
13581                                 break;
13582                         case BIH_COLLISIONTRIANGLE:
13583                                 triangleindex = bihleaf->itemindex;
13584                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13585                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13586                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13587                                 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);
13588                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13589                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13590                                 break;
13591                         case BIH_RENDERTRIANGLE:
13592                                 triangleindex = bihleaf->itemindex;
13593                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13594                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13595                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13596                                 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);
13597                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13598                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13599                                 break;
13600                         }
13601                 }
13602         }
13603
13604         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13605
13606         if (r_showtris.integer || (r_shownormals.value != 0))
13607         {
13608                 if (r_showdisabledepthtest.integer)
13609                 {
13610                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13611                         GL_DepthMask(false);
13612                 }
13613                 else
13614                 {
13615                         GL_BlendFunc(GL_ONE, GL_ZERO);
13616                         GL_DepthMask(true);
13617                 }
13618                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13619                 {
13620                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13621                                 continue;
13622                         rsurface.texture = R_GetCurrentTexture(surface->texture);
13623                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13624                         {
13625                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13626                                 if (r_showtris.value > 0)
13627                                 {
13628                                         if (!rsurface.texture->currentlayers->depthmask)
13629                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13630                                         else if (ent == r_refdef.scene.worldentity)
13631                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13632                                         else
13633                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13634                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13635                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13636                                         RSurf_DrawBatch();
13637                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13638                                         CHECKGLERROR
13639                                 }
13640                                 if (r_shownormals.value < 0)
13641                                 {
13642                                         qglBegin(GL_LINES);
13643                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13644                                         {
13645                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13646                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13647                                                 qglVertex3f(v[0], v[1], v[2]);
13648                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13649                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13650                                                 qglVertex3f(v[0], v[1], v[2]);
13651                                         }
13652                                         qglEnd();
13653                                         CHECKGLERROR
13654                                 }
13655                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13656                                 {
13657                                         qglBegin(GL_LINES);
13658                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13659                                         {
13660                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13661                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13662                                                 qglVertex3f(v[0], v[1], v[2]);
13663                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13664                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13665                                                 qglVertex3f(v[0], v[1], v[2]);
13666                                         }
13667                                         qglEnd();
13668                                         CHECKGLERROR
13669                                         qglBegin(GL_LINES);
13670                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13671                                         {
13672                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13673                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13674                                                 qglVertex3f(v[0], v[1], v[2]);
13675                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13676                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13677                                                 qglVertex3f(v[0], v[1], v[2]);
13678                                         }
13679                                         qglEnd();
13680                                         CHECKGLERROR
13681                                         qglBegin(GL_LINES);
13682                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13683                                         {
13684                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13685                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13686                                                 qglVertex3f(v[0], v[1], v[2]);
13687                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13688                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13689                                                 qglVertex3f(v[0], v[1], v[2]);
13690                                         }
13691                                         qglEnd();
13692                                         CHECKGLERROR
13693                                 }
13694                         }
13695                 }
13696                 rsurface.texture = NULL;
13697         }
13698 }
13699
13700 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13701 int r_maxsurfacelist = 0;
13702 const msurface_t **r_surfacelist = NULL;
13703 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13704 {
13705         int i, j, endj, flagsmask;
13706         dp_model_t *model = r_refdef.scene.worldmodel;
13707         msurface_t *surfaces;
13708         unsigned char *update;
13709         int numsurfacelist = 0;
13710         if (model == NULL)
13711                 return;
13712
13713         if (r_maxsurfacelist < model->num_surfaces)
13714         {
13715                 r_maxsurfacelist = model->num_surfaces;
13716                 if (r_surfacelist)
13717                         Mem_Free((msurface_t**)r_surfacelist);
13718                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13719         }
13720
13721         RSurf_ActiveWorldEntity();
13722
13723         surfaces = model->data_surfaces;
13724         update = model->brushq1.lightmapupdateflags;
13725
13726         // update light styles on this submodel
13727         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13728         {
13729                 model_brush_lightstyleinfo_t *style;
13730                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13731                 {
13732                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13733                         {
13734                                 int *list = style->surfacelist;
13735                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13736                                 for (j = 0;j < style->numsurfaces;j++)
13737                                         update[list[j]] = true;
13738                         }
13739                 }
13740         }
13741
13742         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13743
13744         if (debug)
13745         {
13746                 R_DrawDebugModel();
13747                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13748                 return;
13749         }
13750
13751         rsurface.lightmaptexture = NULL;
13752         rsurface.deluxemaptexture = NULL;
13753         rsurface.uselightmaptexture = false;
13754         rsurface.texture = NULL;
13755         rsurface.rtlight = NULL;
13756         numsurfacelist = 0;
13757         // add visible surfaces to draw list
13758         for (i = 0;i < model->nummodelsurfaces;i++)
13759         {
13760                 j = model->sortedmodelsurfaces[i];
13761                 if (r_refdef.viewcache.world_surfacevisible[j])
13762                         r_surfacelist[numsurfacelist++] = surfaces + j;
13763         }
13764         // update lightmaps if needed
13765         if (model->brushq1.firstrender)
13766         {
13767                 model->brushq1.firstrender = false;
13768                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13769                         if (update[j])
13770                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13771         }
13772         else if (update)
13773         {
13774                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13775                         if (r_refdef.viewcache.world_surfacevisible[j])
13776                                 if (update[j])
13777                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13778         }
13779         // don't do anything if there were no surfaces
13780         if (!numsurfacelist)
13781         {
13782                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13783                 return;
13784         }
13785         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13786
13787         // add to stats if desired
13788         if (r_speeds.integer && !skysurfaces && !depthonly)
13789         {
13790                 r_refdef.stats.world_surfaces += numsurfacelist;
13791                 for (j = 0;j < numsurfacelist;j++)
13792                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13793         }
13794
13795         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13796 }
13797
13798 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13799 {
13800         int i, j, endj, flagsmask;
13801         dp_model_t *model = ent->model;
13802         msurface_t *surfaces;
13803         unsigned char *update;
13804         int numsurfacelist = 0;
13805         if (model == NULL)
13806                 return;
13807
13808         if (r_maxsurfacelist < model->num_surfaces)
13809         {
13810                 r_maxsurfacelist = model->num_surfaces;
13811                 if (r_surfacelist)
13812                         Mem_Free((msurface_t **)r_surfacelist);
13813                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13814         }
13815
13816         // if the model is static it doesn't matter what value we give for
13817         // wantnormals and wanttangents, so this logic uses only rules applicable
13818         // to a model, knowing that they are meaningless otherwise
13819         if (ent == r_refdef.scene.worldentity)
13820                 RSurf_ActiveWorldEntity();
13821         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13822                 RSurf_ActiveModelEntity(ent, false, false, false);
13823         else if (prepass)
13824                 RSurf_ActiveModelEntity(ent, true, true, true);
13825         else if (depthonly)
13826         {
13827                 switch (vid.renderpath)
13828                 {
13829                 case RENDERPATH_GL20:
13830                 case RENDERPATH_D3D9:
13831                 case RENDERPATH_D3D10:
13832                 case RENDERPATH_D3D11:
13833                 case RENDERPATH_SOFT:
13834                 case RENDERPATH_GLES2:
13835                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
13836                         break;
13837                 case RENDERPATH_GL13:
13838                 case RENDERPATH_GL11:
13839                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
13840                         break;
13841                 }
13842         }
13843         else
13844         {
13845                 switch (vid.renderpath)
13846                 {
13847                 case RENDERPATH_GL20:
13848                 case RENDERPATH_D3D9:
13849                 case RENDERPATH_D3D10:
13850                 case RENDERPATH_D3D11:
13851                 case RENDERPATH_SOFT:
13852                 case RENDERPATH_GLES2:
13853                         RSurf_ActiveModelEntity(ent, true, true, false);
13854                         break;
13855                 case RENDERPATH_GL13:
13856                 case RENDERPATH_GL11:
13857                         RSurf_ActiveModelEntity(ent, true, false, false);
13858                         break;
13859                 }
13860         }
13861
13862         surfaces = model->data_surfaces;
13863         update = model->brushq1.lightmapupdateflags;
13864
13865         // update light styles
13866         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13867         {
13868                 model_brush_lightstyleinfo_t *style;
13869                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13870                 {
13871                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13872                         {
13873                                 int *list = style->surfacelist;
13874                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13875                                 for (j = 0;j < style->numsurfaces;j++)
13876                                         update[list[j]] = true;
13877                         }
13878                 }
13879         }
13880
13881         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13882
13883         if (debug)
13884         {
13885                 R_DrawDebugModel();
13886                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13887                 return;
13888         }
13889
13890         rsurface.lightmaptexture = NULL;
13891         rsurface.deluxemaptexture = NULL;
13892         rsurface.uselightmaptexture = false;
13893         rsurface.texture = NULL;
13894         rsurface.rtlight = NULL;
13895         numsurfacelist = 0;
13896         // add visible surfaces to draw list
13897         for (i = 0;i < model->nummodelsurfaces;i++)
13898                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
13899         // don't do anything if there were no surfaces
13900         if (!numsurfacelist)
13901         {
13902                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13903                 return;
13904         }
13905         // update lightmaps if needed
13906         if (update)
13907         {
13908                 int updated = 0;
13909                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13910                 {
13911                         if (update[j])
13912                         {
13913                                 updated++;
13914                                 R_BuildLightMap(ent, surfaces + j);
13915                         }
13916                 }
13917         }
13918         if (update)
13919                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13920                         if (update[j])
13921                                 R_BuildLightMap(ent, surfaces + j);
13922         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13923
13924         // add to stats if desired
13925         if (r_speeds.integer && !skysurfaces && !depthonly)
13926         {
13927                 r_refdef.stats.entities_surfaces += numsurfacelist;
13928                 for (j = 0;j < numsurfacelist;j++)
13929                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
13930         }
13931
13932         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13933 }
13934
13935 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
13936 {
13937         static texture_t texture;
13938         static msurface_t surface;
13939         const msurface_t *surfacelist = &surface;
13940
13941         // fake enough texture and surface state to render this geometry
13942
13943         texture.update_lastrenderframe = -1; // regenerate this texture
13944         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
13945         texture.currentskinframe = skinframe;
13946         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
13947         texture.offsetmapping = OFFSETMAPPING_OFF;
13948         texture.offsetscale = 1;
13949         texture.specularscalemod = 1;
13950         texture.specularpowermod = 1;
13951
13952         surface.texture = &texture;
13953         surface.num_triangles = numtriangles;
13954         surface.num_firsttriangle = firsttriangle;
13955         surface.num_vertices = numvertices;
13956         surface.num_firstvertex = firstvertex;
13957
13958         // now render it
13959         rsurface.texture = R_GetCurrentTexture(surface.texture);
13960         rsurface.lightmaptexture = NULL;
13961         rsurface.deluxemaptexture = NULL;
13962         rsurface.uselightmaptexture = false;
13963         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
13964 }
13965
13966 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)
13967 {
13968         static msurface_t surface;
13969         const msurface_t *surfacelist = &surface;
13970
13971         // fake enough texture and surface state to render this geometry
13972         surface.texture = texture;
13973         surface.num_triangles = numtriangles;
13974         surface.num_firsttriangle = firsttriangle;
13975         surface.num_vertices = numvertices;
13976         surface.num_firstvertex = firstvertex;
13977
13978         // now render it
13979         rsurface.texture = R_GetCurrentTexture(surface.texture);
13980         rsurface.lightmaptexture = NULL;
13981         rsurface.deluxemaptexture = NULL;
13982         rsurface.uselightmaptexture = false;
13983         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
13984 }