]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix an error in the HLSL shader (unintentional use of mix rather than lerp function)
[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 *builtincgshaderstring =
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 *cgshaderstring = NULL;
3343 char *hlslshaderstring = NULL;
3344
3345 //=======================================================================================================================================================
3346
3347 typedef struct shaderpermutationinfo_s
3348 {
3349         const char *pretext;
3350         const char *name;
3351 }
3352 shaderpermutationinfo_t;
3353
3354 typedef struct shadermodeinfo_s
3355 {
3356         const char *vertexfilename;
3357         const char *geometryfilename;
3358         const char *fragmentfilename;
3359         const char *pretext;
3360         const char *name;
3361 }
3362 shadermodeinfo_t;
3363
3364 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3365 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3366 {
3367         {"#define USEDIFFUSE\n", " diffuse"},
3368         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3369         {"#define USEVIEWTINT\n", " viewtint"},
3370         {"#define USECOLORMAPPING\n", " colormapping"},
3371         {"#define USESATURATION\n", " saturation"},
3372         {"#define USEFOGINSIDE\n", " foginside"},
3373         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3374         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3375         {"#define USEGAMMARAMPS\n", " gammaramps"},
3376         {"#define USECUBEFILTER\n", " cubefilter"},
3377         {"#define USEGLOW\n", " glow"},
3378         {"#define USEBLOOM\n", " bloom"},
3379         {"#define USESPECULAR\n", " specular"},
3380         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3381         {"#define USEREFLECTION\n", " reflection"},
3382         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3383         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3384         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3385         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3386         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3387         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3388         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3389         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3390         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3391         {"#define USEALPHAKILL\n", " alphakill"},
3392         {"#define USEREFLECTCUBE\n", " reflectcube"},
3393         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3394 };
3395
3396 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3397 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3398 {
3399         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3400         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3401         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3402         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3403         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3404         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3405         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3406         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3407         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3408         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3409         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3410         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3411         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3412         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3413         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3414         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3415 };
3416
3417 #ifdef SUPPORTCG
3418 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3419 {
3420         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3421         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3422         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3423         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3424         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3425         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3426         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3427         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3428         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3429         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3430         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3431         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3432         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3433         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3434         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3435         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3436 };
3437 #endif
3438
3439 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3440 {
3441         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3442         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3443         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3444         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3445         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3446         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3447         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3448         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3449         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3450         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3451         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3452         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3453         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3454         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3455         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3456         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3457 };
3458
3459 struct r_glsl_permutation_s;
3460 typedef struct r_glsl_permutation_s
3461 {
3462         /// hash lookup data
3463         struct r_glsl_permutation_s *hashnext;
3464         unsigned int mode;
3465         unsigned int permutation;
3466
3467         /// indicates if we have tried compiling this permutation already
3468         qboolean compiled;
3469         /// 0 if compilation failed
3470         int program;
3471         // texture units assigned to each detected uniform
3472         int tex_Texture_First;
3473         int tex_Texture_Second;
3474         int tex_Texture_GammaRamps;
3475         int tex_Texture_Normal;
3476         int tex_Texture_Color;
3477         int tex_Texture_Gloss;
3478         int tex_Texture_Glow;
3479         int tex_Texture_SecondaryNormal;
3480         int tex_Texture_SecondaryColor;
3481         int tex_Texture_SecondaryGloss;
3482         int tex_Texture_SecondaryGlow;
3483         int tex_Texture_Pants;
3484         int tex_Texture_Shirt;
3485         int tex_Texture_FogHeightTexture;
3486         int tex_Texture_FogMask;
3487         int tex_Texture_Lightmap;
3488         int tex_Texture_Deluxemap;
3489         int tex_Texture_Attenuation;
3490         int tex_Texture_Cube;
3491         int tex_Texture_Refraction;
3492         int tex_Texture_Reflection;
3493         int tex_Texture_ShadowMap2D;
3494         int tex_Texture_CubeProjection;
3495         int tex_Texture_ScreenDepth;
3496         int tex_Texture_ScreenNormalMap;
3497         int tex_Texture_ScreenDiffuse;
3498         int tex_Texture_ScreenSpecular;
3499         int tex_Texture_ReflectMask;
3500         int tex_Texture_ReflectCube;
3501         /// locations of detected uniforms in program object, or -1 if not found
3502         int loc_Texture_First;
3503         int loc_Texture_Second;
3504         int loc_Texture_GammaRamps;
3505         int loc_Texture_Normal;
3506         int loc_Texture_Color;
3507         int loc_Texture_Gloss;
3508         int loc_Texture_Glow;
3509         int loc_Texture_SecondaryNormal;
3510         int loc_Texture_SecondaryColor;
3511         int loc_Texture_SecondaryGloss;
3512         int loc_Texture_SecondaryGlow;
3513         int loc_Texture_Pants;
3514         int loc_Texture_Shirt;
3515         int loc_Texture_FogHeightTexture;
3516         int loc_Texture_FogMask;
3517         int loc_Texture_Lightmap;
3518         int loc_Texture_Deluxemap;
3519         int loc_Texture_Attenuation;
3520         int loc_Texture_Cube;
3521         int loc_Texture_Refraction;
3522         int loc_Texture_Reflection;
3523         int loc_Texture_ShadowMap2D;
3524         int loc_Texture_CubeProjection;
3525         int loc_Texture_ScreenDepth;
3526         int loc_Texture_ScreenNormalMap;
3527         int loc_Texture_ScreenDiffuse;
3528         int loc_Texture_ScreenSpecular;
3529         int loc_Texture_ReflectMask;
3530         int loc_Texture_ReflectCube;
3531         int loc_Alpha;
3532         int loc_BloomBlur_Parameters;
3533         int loc_ClientTime;
3534         int loc_Color_Ambient;
3535         int loc_Color_Diffuse;
3536         int loc_Color_Specular;
3537         int loc_Color_Glow;
3538         int loc_Color_Pants;
3539         int loc_Color_Shirt;
3540         int loc_DeferredColor_Ambient;
3541         int loc_DeferredColor_Diffuse;
3542         int loc_DeferredColor_Specular;
3543         int loc_DeferredMod_Diffuse;
3544         int loc_DeferredMod_Specular;
3545         int loc_DistortScaleRefractReflect;
3546         int loc_EyePosition;
3547         int loc_FogColor;
3548         int loc_FogHeightFade;
3549         int loc_FogPlane;
3550         int loc_FogPlaneViewDist;
3551         int loc_FogRangeRecip;
3552         int loc_LightColor;
3553         int loc_LightDir;
3554         int loc_LightPosition;
3555         int loc_OffsetMapping_Scale;
3556         int loc_PixelSize;
3557         int loc_ReflectColor;
3558         int loc_ReflectFactor;
3559         int loc_ReflectOffset;
3560         int loc_RefractColor;
3561         int loc_Saturation;
3562         int loc_ScreenCenterRefractReflect;
3563         int loc_ScreenScaleRefractReflect;
3564         int loc_ScreenToDepth;
3565         int loc_ShadowMap_Parameters;
3566         int loc_ShadowMap_TextureScale;
3567         int loc_SpecularPower;
3568         int loc_UserVec1;
3569         int loc_UserVec2;
3570         int loc_UserVec3;
3571         int loc_UserVec4;
3572         int loc_ViewTintColor;
3573         int loc_ViewToLight;
3574         int loc_ModelToLight;
3575         int loc_TexMatrix;
3576         int loc_BackgroundTexMatrix;
3577         int loc_ModelViewProjectionMatrix;
3578         int loc_ModelViewMatrix;
3579         int loc_PixelToScreenTexCoord;
3580         int loc_ModelToReflectCube;
3581         int loc_ShadowMapMatrix;
3582         int loc_BloomColorSubtract;
3583         int loc_NormalmapScrollBlend;
3584 }
3585 r_glsl_permutation_t;
3586
3587 #define SHADERPERMUTATION_HASHSIZE 256
3588
3589
3590 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3591 // these can NOT degrade! only use for simple stuff
3592 enum
3593 {
3594         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3595         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3596         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3597         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3598         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3599         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
3600 };
3601 #define SHADERSTATICPARMS_COUNT 6
3602
3603 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3604 static int shaderstaticparms_count = 0;
3605
3606 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3607 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3608 qboolean R_CompileShader_CheckStaticParms(void)
3609 {
3610         static int r_compileshader_staticparms_save[1];
3611         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3612         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3613
3614         // detect all
3615         if (r_glsl_saturation_redcompensate.integer)
3616                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3617         if (r_shadow_glossexact.integer)
3618                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3619         if (r_glsl_postprocess.integer)
3620         {
3621                 if (r_glsl_postprocess_uservec1_enable.integer)
3622                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3623                 if (r_glsl_postprocess_uservec2_enable.integer)
3624                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3625                 if (r_glsl_postprocess_uservec3_enable.integer)
3626                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3627                 if (r_glsl_postprocess_uservec4_enable.integer)
3628                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3629         }
3630         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3631 }
3632
3633 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3634         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3635                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3636         else \
3637                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3638 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3639 {
3640         shaderstaticparms_count = 0;
3641
3642         // emit all
3643         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3644         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3645         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3646         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3647         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3648         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3649 }
3650
3651 /// information about each possible shader permutation
3652 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3653 /// currently selected permutation
3654 r_glsl_permutation_t *r_glsl_permutation;
3655 /// storage for permutations linked in the hash table
3656 memexpandablearray_t r_glsl_permutationarray;
3657
3658 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3659 {
3660         //unsigned int hashdepth = 0;
3661         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3662         r_glsl_permutation_t *p;
3663         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3664         {
3665                 if (p->mode == mode && p->permutation == permutation)
3666                 {
3667                         //if (hashdepth > 10)
3668                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3669                         return p;
3670                 }
3671                 //hashdepth++;
3672         }
3673         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3674         p->mode = mode;
3675         p->permutation = permutation;
3676         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3677         r_glsl_permutationhash[mode][hashindex] = p;
3678         //if (hashdepth > 10)
3679         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3680         return p;
3681 }
3682
3683 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3684 {
3685         char *shaderstring;
3686         if (!filename || !filename[0])
3687                 return NULL;
3688         if (!strcmp(filename, "glsl/default.glsl"))
3689         {
3690                 if (!glslshaderstring)
3691                 {
3692                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3693                         if (glslshaderstring)
3694                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3695                         else
3696                                 glslshaderstring = (char *)builtinshaderstring;
3697                 }
3698                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3699                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3700                 return shaderstring;
3701         }
3702         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3703         if (shaderstring)
3704         {
3705                 if (printfromdisknotice)
3706                         Con_DPrintf("from disk %s... ", filename);
3707                 return shaderstring;
3708         }
3709         return shaderstring;
3710 }
3711
3712 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3713 {
3714         int i;
3715         int sampler;
3716         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3717         char *vertexstring, *geometrystring, *fragmentstring;
3718         char permutationname[256];
3719         int vertstrings_count = 0;
3720         int geomstrings_count = 0;
3721         int fragstrings_count = 0;
3722         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3723         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3724         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3725
3726         if (p->compiled)
3727                 return;
3728         p->compiled = true;
3729         p->program = 0;
3730
3731         permutationname[0] = 0;
3732         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3733         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3734         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3735
3736         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3737
3738         // the first pretext is which type of shader to compile as
3739         // (later these will all be bound together as a program object)
3740         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3741         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3742         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3743
3744         // the second pretext is the mode (for example a light source)
3745         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3746         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3747         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3748         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3749
3750         // now add all the permutation pretexts
3751         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3752         {
3753                 if (permutation & (1<<i))
3754                 {
3755                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3756                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3757                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3758                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3759                 }
3760                 else
3761                 {
3762                         // keep line numbers correct
3763                         vertstrings_list[vertstrings_count++] = "\n";
3764                         geomstrings_list[geomstrings_count++] = "\n";
3765                         fragstrings_list[fragstrings_count++] = "\n";
3766                 }
3767         }
3768
3769         // add static parms
3770         R_CompileShader_AddStaticParms(mode, permutation);
3771         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3772         vertstrings_count += shaderstaticparms_count;
3773         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3774         geomstrings_count += shaderstaticparms_count;
3775         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3776         fragstrings_count += shaderstaticparms_count;
3777
3778         // now append the shader text itself
3779         vertstrings_list[vertstrings_count++] = vertexstring;
3780         geomstrings_list[geomstrings_count++] = geometrystring;
3781         fragstrings_list[fragstrings_count++] = fragmentstring;
3782
3783         // if any sources were NULL, clear the respective list
3784         if (!vertexstring)
3785                 vertstrings_count = 0;
3786         if (!geometrystring)
3787                 geomstrings_count = 0;
3788         if (!fragmentstring)
3789                 fragstrings_count = 0;
3790
3791         // compile the shader program
3792         if (vertstrings_count + geomstrings_count + fragstrings_count)
3793                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3794         if (p->program)
3795         {
3796                 CHECKGLERROR
3797                 qglUseProgram(p->program);CHECKGLERROR
3798                 // look up all the uniform variable names we care about, so we don't
3799                 // have to look them up every time we set them
3800
3801                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
3802                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
3803                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
3804                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
3805                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
3806                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
3807                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
3808                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
3809                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
3810                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
3811                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
3812                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
3813                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
3814                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
3815                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
3816                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
3817                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
3818                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
3819                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
3820                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
3821                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
3822                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
3823                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
3824                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
3825                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
3826                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
3827                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
3828                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
3829                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
3830                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
3831                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
3832                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
3833                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
3834                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
3835                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
3836                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
3837                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
3838                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
3839                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
3840                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
3841                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
3842                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
3843                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
3844                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
3845                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
3846                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
3847                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
3848                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
3849                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
3850                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
3851                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
3852                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
3853                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
3854                 p->loc_OffsetMapping_Scale        = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
3855                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
3856                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
3857                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
3858                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
3859                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
3860                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
3861                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
3862                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
3863                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
3864                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
3865                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
3866                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
3867                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
3868                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
3869                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
3870                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
3871                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
3872                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
3873                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
3874                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
3875                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
3876                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
3877                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
3878                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
3879                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
3880                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
3881                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
3882                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
3883                 // initialize the samplers to refer to the texture units we use
3884                 p->tex_Texture_First = -1;
3885                 p->tex_Texture_Second = -1;
3886                 p->tex_Texture_GammaRamps = -1;
3887                 p->tex_Texture_Normal = -1;
3888                 p->tex_Texture_Color = -1;
3889                 p->tex_Texture_Gloss = -1;
3890                 p->tex_Texture_Glow = -1;
3891                 p->tex_Texture_SecondaryNormal = -1;
3892                 p->tex_Texture_SecondaryColor = -1;
3893                 p->tex_Texture_SecondaryGloss = -1;
3894                 p->tex_Texture_SecondaryGlow = -1;
3895                 p->tex_Texture_Pants = -1;
3896                 p->tex_Texture_Shirt = -1;
3897                 p->tex_Texture_FogHeightTexture = -1;
3898                 p->tex_Texture_FogMask = -1;
3899                 p->tex_Texture_Lightmap = -1;
3900                 p->tex_Texture_Deluxemap = -1;
3901                 p->tex_Texture_Attenuation = -1;
3902                 p->tex_Texture_Cube = -1;
3903                 p->tex_Texture_Refraction = -1;
3904                 p->tex_Texture_Reflection = -1;
3905                 p->tex_Texture_ShadowMap2D = -1;
3906                 p->tex_Texture_CubeProjection = -1;
3907                 p->tex_Texture_ScreenDepth = -1;
3908                 p->tex_Texture_ScreenNormalMap = -1;
3909                 p->tex_Texture_ScreenDiffuse = -1;
3910                 p->tex_Texture_ScreenSpecular = -1;
3911                 p->tex_Texture_ReflectMask = -1;
3912                 p->tex_Texture_ReflectCube = -1;
3913                 sampler = 0;
3914                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
3915                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
3916                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
3917                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
3918                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
3919                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
3920                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
3921                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
3922                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
3923                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
3924                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
3925                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
3926                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
3927                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
3928                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
3929                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
3930                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
3931                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
3932                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
3933                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
3934                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
3935                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
3936                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
3937                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
3938                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
3939                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
3940                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
3941                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
3942                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
3943                 CHECKGLERROR
3944                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
3945         }
3946         else
3947                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3948
3949         // free the strings
3950         if (vertexstring)
3951                 Mem_Free(vertexstring);
3952         if (geometrystring)
3953                 Mem_Free(geometrystring);
3954         if (fragmentstring)
3955                 Mem_Free(fragmentstring);
3956 }
3957
3958 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3959 {
3960         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3961         if (r_glsl_permutation != perm)
3962         {
3963                 r_glsl_permutation = perm;
3964                 if (!r_glsl_permutation->program)
3965                 {
3966                         if (!r_glsl_permutation->compiled)
3967                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3968                         if (!r_glsl_permutation->program)
3969                         {
3970                                 // remove features until we find a valid permutation
3971                                 int i;
3972                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3973                                 {
3974                                         // reduce i more quickly whenever it would not remove any bits
3975                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3976                                         if (!(permutation & j))
3977                                                 continue;
3978                                         permutation -= j;
3979                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3980                                         if (!r_glsl_permutation->compiled)
3981                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3982                                         if (r_glsl_permutation->program)
3983                                                 break;
3984                                 }
3985                                 if (i >= SHADERPERMUTATION_COUNT)
3986                                 {
3987                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3988                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3989                                         qglUseProgram(0);CHECKGLERROR
3990                                         return; // no bit left to clear, entire mode is broken
3991                                 }
3992                         }
3993                 }
3994                 CHECKGLERROR
3995                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
3996         }
3997         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3998         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3999         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
4000 }
4001
4002 #ifdef SUPPORTCG
4003 #include <Cg/cgGL.h>
4004 struct r_cg_permutation_s;
4005 typedef struct r_cg_permutation_s
4006 {
4007         /// hash lookup data
4008         struct r_cg_permutation_s *hashnext;
4009         unsigned int mode;
4010         unsigned int permutation;
4011
4012         /// indicates if we have tried compiling this permutation already
4013         qboolean compiled;
4014         /// 0 if compilation failed
4015         CGprogram vprogram;
4016         CGprogram fprogram;
4017         /// locations of detected parameters in programs, or NULL if not found
4018         CGparameter vp_EyePosition;
4019         CGparameter vp_FogPlane;
4020         CGparameter vp_LightDir;
4021         CGparameter vp_LightPosition;
4022         CGparameter vp_ModelToLight;
4023         CGparameter vp_TexMatrix;
4024         CGparameter vp_BackgroundTexMatrix;
4025         CGparameter vp_ModelViewProjectionMatrix;
4026         CGparameter vp_ModelViewMatrix;
4027         CGparameter vp_ShadowMapMatrix;
4028
4029         CGparameter fp_Texture_First;
4030         CGparameter fp_Texture_Second;
4031         CGparameter fp_Texture_GammaRamps;
4032         CGparameter fp_Texture_Normal;
4033         CGparameter fp_Texture_Color;
4034         CGparameter fp_Texture_Gloss;
4035         CGparameter fp_Texture_Glow;
4036         CGparameter fp_Texture_SecondaryNormal;
4037         CGparameter fp_Texture_SecondaryColor;
4038         CGparameter fp_Texture_SecondaryGloss;
4039         CGparameter fp_Texture_SecondaryGlow;
4040         CGparameter fp_Texture_Pants;
4041         CGparameter fp_Texture_Shirt;
4042         CGparameter fp_Texture_FogHeightTexture;
4043         CGparameter fp_Texture_FogMask;
4044         CGparameter fp_Texture_Lightmap;
4045         CGparameter fp_Texture_Deluxemap;
4046         CGparameter fp_Texture_Attenuation;
4047         CGparameter fp_Texture_Cube;
4048         CGparameter fp_Texture_Refraction;
4049         CGparameter fp_Texture_Reflection;
4050         CGparameter fp_Texture_ShadowMap2D;
4051         CGparameter fp_Texture_CubeProjection;
4052         CGparameter fp_Texture_ScreenDepth;
4053         CGparameter fp_Texture_ScreenNormalMap;
4054         CGparameter fp_Texture_ScreenDiffuse;
4055         CGparameter fp_Texture_ScreenSpecular;
4056         CGparameter fp_Texture_ReflectMask;
4057         CGparameter fp_Texture_ReflectCube;
4058         CGparameter fp_Alpha;
4059         CGparameter fp_BloomBlur_Parameters;
4060         CGparameter fp_ClientTime;
4061         CGparameter fp_Color_Ambient;
4062         CGparameter fp_Color_Diffuse;
4063         CGparameter fp_Color_Specular;
4064         CGparameter fp_Color_Glow;
4065         CGparameter fp_Color_Pants;
4066         CGparameter fp_Color_Shirt;
4067         CGparameter fp_DeferredColor_Ambient;
4068         CGparameter fp_DeferredColor_Diffuse;
4069         CGparameter fp_DeferredColor_Specular;
4070         CGparameter fp_DeferredMod_Diffuse;
4071         CGparameter fp_DeferredMod_Specular;
4072         CGparameter fp_DistortScaleRefractReflect;
4073         CGparameter fp_EyePosition;
4074         CGparameter fp_FogColor;
4075         CGparameter fp_FogHeightFade;
4076         CGparameter fp_FogPlane;
4077         CGparameter fp_FogPlaneViewDist;
4078         CGparameter fp_FogRangeRecip;
4079         CGparameter fp_LightColor;
4080         CGparameter fp_LightDir;
4081         CGparameter fp_LightPosition;
4082         CGparameter fp_OffsetMapping_Scale;
4083         CGparameter fp_PixelSize;
4084         CGparameter fp_ReflectColor;
4085         CGparameter fp_ReflectFactor;
4086         CGparameter fp_ReflectOffset;
4087         CGparameter fp_RefractColor;
4088         CGparameter fp_Saturation;
4089         CGparameter fp_ScreenCenterRefractReflect;
4090         CGparameter fp_ScreenScaleRefractReflect;
4091         CGparameter fp_ScreenToDepth;
4092         CGparameter fp_ShadowMap_Parameters;
4093         CGparameter fp_ShadowMap_TextureScale;
4094         CGparameter fp_SpecularPower;
4095         CGparameter fp_UserVec1;
4096         CGparameter fp_UserVec2;
4097         CGparameter fp_UserVec3;
4098         CGparameter fp_UserVec4;
4099         CGparameter fp_ViewTintColor;
4100         CGparameter fp_ViewToLight;
4101         CGparameter fp_PixelToScreenTexCoord;
4102         CGparameter fp_ModelToReflectCube;
4103         CGparameter fp_BloomColorSubtract;
4104         CGparameter fp_NormalmapScrollBlend;
4105 }
4106 r_cg_permutation_t;
4107
4108 /// information about each possible shader permutation
4109 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4110 /// currently selected permutation
4111 r_cg_permutation_t *r_cg_permutation;
4112 /// storage for permutations linked in the hash table
4113 memexpandablearray_t r_cg_permutationarray;
4114
4115 #define CHECKCGERROR {CGerror err = cgGetError(), err2 = err;if (err){Con_Printf("%s:%i CG error %i: %s : %s\n", __FILE__, __LINE__, err, cgGetErrorString(err), cgGetLastErrorString(&err2));if (err == 1) Con_Printf("last listing:\n%s\n", cgGetLastListing(vid.cgcontext));}}
4116
4117 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4118 {
4119         //unsigned int hashdepth = 0;
4120         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4121         r_cg_permutation_t *p;
4122         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4123         {
4124                 if (p->mode == mode && p->permutation == permutation)
4125                 {
4126                         //if (hashdepth > 10)
4127                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4128                         return p;
4129                 }
4130                 //hashdepth++;
4131         }
4132         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4133         p->mode = mode;
4134         p->permutation = permutation;
4135         p->hashnext = r_cg_permutationhash[mode][hashindex];
4136         r_cg_permutationhash[mode][hashindex] = p;
4137         //if (hashdepth > 10)
4138         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4139         return p;
4140 }
4141
4142 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4143 {
4144         char *shaderstring;
4145         if (!filename || !filename[0])
4146                 return NULL;
4147         if (!strcmp(filename, "cg/default.cg"))
4148         {
4149                 if (!cgshaderstring)
4150                 {
4151                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4152                         if (cgshaderstring)
4153                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4154                         else
4155                                 cgshaderstring = (char *)builtincgshaderstring;
4156                 }
4157                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4158                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4159                 return shaderstring;
4160         }
4161         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4162         if (shaderstring)
4163         {
4164                 if (printfromdisknotice)
4165                         Con_DPrintf("from disk %s... ", filename);
4166                 return shaderstring;
4167         }
4168         return shaderstring;
4169 }
4170
4171 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4172 {
4173         // TODO: load or create .fp and .vp shader files
4174 }
4175
4176 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4177 {
4178         int i;
4179         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4180         int vertstring_length = 0;
4181         int geomstring_length = 0;
4182         int fragstring_length = 0;
4183         char *t;
4184         char *vertexstring, *geometrystring, *fragmentstring;
4185         char *vertstring, *geomstring, *fragstring;
4186         char permutationname[256];
4187         char cachename[256];
4188         CGprofile vertexProfile;
4189         CGprofile fragmentProfile;
4190         int vertstrings_count = 0;
4191         int geomstrings_count = 0;
4192         int fragstrings_count = 0;
4193         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4194         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4195         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4196
4197         if (p->compiled)
4198                 return;
4199         p->compiled = true;
4200         p->vprogram = NULL;
4201         p->fprogram = NULL;
4202
4203         permutationname[0] = 0;
4204         cachename[0] = 0;
4205         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4206         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4207         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4208
4209         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4210         strlcat(cachename, "cg/", sizeof(cachename));
4211
4212         // the first pretext is which type of shader to compile as
4213         // (later these will all be bound together as a program object)
4214         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4215         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4216         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4217
4218         // the second pretext is the mode (for example a light source)
4219         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4220         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4221         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4222         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4223         strlcat(cachename, modeinfo->name, sizeof(cachename));
4224
4225         // now add all the permutation pretexts
4226         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4227         {
4228                 if (permutation & (1<<i))
4229                 {
4230                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4231                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4232                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4233                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4234                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4235                 }
4236                 else
4237                 {
4238                         // keep line numbers correct
4239                         vertstrings_list[vertstrings_count++] = "\n";
4240                         geomstrings_list[geomstrings_count++] = "\n";
4241                         fragstrings_list[fragstrings_count++] = "\n";
4242                 }
4243         }
4244
4245         // add static parms
4246         R_CompileShader_AddStaticParms(mode, permutation);
4247         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4248         vertstrings_count += shaderstaticparms_count;
4249         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4250         geomstrings_count += shaderstaticparms_count;
4251         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4252         fragstrings_count += shaderstaticparms_count;
4253
4254         // replace spaces in the cachename with _ characters
4255         for (i = 0;cachename[i];i++)
4256                 if (cachename[i] == ' ')
4257                         cachename[i] = '_';
4258
4259         // now append the shader text itself
4260         vertstrings_list[vertstrings_count++] = vertexstring;
4261         geomstrings_list[geomstrings_count++] = geometrystring;
4262         fragstrings_list[fragstrings_count++] = fragmentstring;
4263
4264         // if any sources were NULL, clear the respective list
4265         if (!vertexstring)
4266                 vertstrings_count = 0;
4267         if (!geometrystring)
4268                 geomstrings_count = 0;
4269         if (!fragmentstring)
4270                 fragstrings_count = 0;
4271
4272         vertstring_length = 0;
4273         for (i = 0;i < vertstrings_count;i++)
4274                 vertstring_length += strlen(vertstrings_list[i]);
4275         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4276         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4277                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4278
4279         geomstring_length = 0;
4280         for (i = 0;i < geomstrings_count;i++)
4281                 geomstring_length += strlen(geomstrings_list[i]);
4282         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4283         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4284                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4285
4286         fragstring_length = 0;
4287         for (i = 0;i < fragstrings_count;i++)
4288                 fragstring_length += strlen(fragstrings_list[i]);
4289         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4290         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4291                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4292
4293         CHECKGLERROR
4294         CHECKCGERROR
4295         //vertexProfile = CG_PROFILE_ARBVP1;
4296         //fragmentProfile = CG_PROFILE_ARBFP1;
4297         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4298         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4299         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4300         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4301         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4302         CHECKGLERROR
4303
4304         // try to load the cached shader, or generate one
4305         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4306
4307         // if caching failed, do a dynamic compile for now
4308         CHECKCGERROR
4309         if (vertstring[0] && !p->vprogram)
4310                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4311         CHECKCGERROR
4312         if (fragstring[0] && !p->fprogram)
4313                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4314         CHECKCGERROR
4315
4316         // look up all the uniform variable names we care about, so we don't
4317         // have to look them up every time we set them
4318         if (p->vprogram)
4319         {
4320                 CHECKCGERROR
4321                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4322                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4323                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4324                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4325                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4326                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4327                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4328                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4329                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4330                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4331                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4332                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4333                 CHECKCGERROR
4334         }
4335         if (p->fprogram)
4336         {
4337                 CHECKCGERROR
4338                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4339                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4340                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4341                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4342                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4343                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4344                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4345                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4346                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4347                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4348                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4349                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4350                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4351                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4352                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4353                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4354                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4355                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4356                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4357                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4358                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4359                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4360                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4361                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4362                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4363                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4364                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4365                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4366                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4367                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4368                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4369                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4370                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4371                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4372                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4373                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4374                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4375                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4376                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4377                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4378                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4379                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4380                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4381                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4382                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4383                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4384                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4385                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4386                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4387                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4388                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4389                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4390                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4391                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4392                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4393                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4394                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4395                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4396                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4397                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4398                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4399                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4400                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4401                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4402                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4403                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4404                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4405                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4406                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4407                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4408                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4409                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4410                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4411                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4412                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4413                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4414                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4415                 p->fp_NormalmapScrollBlend       = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4416                 CHECKCGERROR
4417         }
4418
4419         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4420                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4421         else
4422                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4423
4424         // free the strings
4425         if (vertstring)
4426                 Mem_Free(vertstring);
4427         if (geomstring)
4428                 Mem_Free(geomstring);
4429         if (fragstring)
4430                 Mem_Free(fragstring);
4431         if (vertexstring)
4432                 Mem_Free(vertexstring);
4433         if (geometrystring)
4434                 Mem_Free(geometrystring);
4435         if (fragmentstring)
4436                 Mem_Free(fragmentstring);
4437 }
4438
4439 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4440 {
4441         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4442         CHECKGLERROR
4443         CHECKCGERROR
4444         if (r_cg_permutation != perm)
4445         {
4446                 r_cg_permutation = perm;
4447                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4448                 {
4449                         if (!r_cg_permutation->compiled)
4450                                 R_CG_CompilePermutation(perm, mode, permutation);
4451                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4452                         {
4453                                 // remove features until we find a valid permutation
4454                                 int i;
4455                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4456                                 {
4457                                         // reduce i more quickly whenever it would not remove any bits
4458                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4459                                         if (!(permutation & j))
4460                                                 continue;
4461                                         permutation -= j;
4462                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4463                                         if (!r_cg_permutation->compiled)
4464                                                 R_CG_CompilePermutation(perm, mode, permutation);
4465                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4466                                                 break;
4467                                 }
4468                                 if (i >= SHADERPERMUTATION_COUNT)
4469                                 {
4470                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4471                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4472                                         return; // no bit left to clear, entire mode is broken
4473                                 }
4474                         }
4475                 }
4476                 CHECKGLERROR
4477                 CHECKCGERROR
4478                 if (r_cg_permutation->vprogram)
4479                 {
4480                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4481                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4482                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4483                 }
4484                 else
4485                 {
4486                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4487                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4488                 }
4489                 if (r_cg_permutation->fprogram)
4490                 {
4491                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4492                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4493                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4494                 }
4495                 else
4496                 {
4497                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4498                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4499                 }
4500         }
4501         CHECKCGERROR
4502         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4503         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4504         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4505 }
4506
4507 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4508 {
4509         cgGLSetTextureParameter(param, R_GetTexture(tex));
4510         cgGLEnableTextureParameter(param);
4511 }
4512 #endif
4513
4514 #ifdef SUPPORTD3D
4515
4516 #ifdef SUPPORTD3D
4517 #include <d3d9.h>
4518 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4519 extern D3DCAPS9 vid_d3d9caps;
4520 #endif
4521
4522 struct r_hlsl_permutation_s;
4523 typedef struct r_hlsl_permutation_s
4524 {
4525         /// hash lookup data
4526         struct r_hlsl_permutation_s *hashnext;
4527         unsigned int mode;
4528         unsigned int permutation;
4529
4530         /// indicates if we have tried compiling this permutation already
4531         qboolean compiled;
4532         /// NULL if compilation failed
4533         IDirect3DVertexShader9 *vertexshader;
4534         IDirect3DPixelShader9 *pixelshader;
4535 }
4536 r_hlsl_permutation_t;
4537
4538 typedef enum D3DVSREGISTER_e
4539 {
4540         D3DVSREGISTER_TexMatrix = 0, // float4x4
4541         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4542         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4543         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4544         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4545         D3DVSREGISTER_ModelToLight = 20, // float4x4
4546         D3DVSREGISTER_EyePosition = 24,
4547         D3DVSREGISTER_FogPlane = 25,
4548         D3DVSREGISTER_LightDir = 26,
4549         D3DVSREGISTER_LightPosition = 27,
4550 }
4551 D3DVSREGISTER_t;
4552
4553 typedef enum D3DPSREGISTER_e
4554 {
4555         D3DPSREGISTER_Alpha = 0,
4556         D3DPSREGISTER_BloomBlur_Parameters = 1,
4557         D3DPSREGISTER_ClientTime = 2,
4558         D3DPSREGISTER_Color_Ambient = 3,
4559         D3DPSREGISTER_Color_Diffuse = 4,
4560         D3DPSREGISTER_Color_Specular = 5,
4561         D3DPSREGISTER_Color_Glow = 6,
4562         D3DPSREGISTER_Color_Pants = 7,
4563         D3DPSREGISTER_Color_Shirt = 8,
4564         D3DPSREGISTER_DeferredColor_Ambient = 9,
4565         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4566         D3DPSREGISTER_DeferredColor_Specular = 11,
4567         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4568         D3DPSREGISTER_DeferredMod_Specular = 13,
4569         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4570         D3DPSREGISTER_EyePosition = 15, // unused
4571         D3DPSREGISTER_FogColor = 16,
4572         D3DPSREGISTER_FogHeightFade = 17,
4573         D3DPSREGISTER_FogPlane = 18,
4574         D3DPSREGISTER_FogPlaneViewDist = 19,
4575         D3DPSREGISTER_FogRangeRecip = 20,
4576         D3DPSREGISTER_LightColor = 21,
4577         D3DPSREGISTER_LightDir = 22, // unused
4578         D3DPSREGISTER_LightPosition = 23,
4579         D3DPSREGISTER_OffsetMapping_Scale = 24,
4580         D3DPSREGISTER_PixelSize = 25,
4581         D3DPSREGISTER_ReflectColor = 26,
4582         D3DPSREGISTER_ReflectFactor = 27,
4583         D3DPSREGISTER_ReflectOffset = 28,
4584         D3DPSREGISTER_RefractColor = 29,
4585         D3DPSREGISTER_Saturation = 30,
4586         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4587         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4588         D3DPSREGISTER_ScreenToDepth = 33,
4589         D3DPSREGISTER_ShadowMap_Parameters = 34,
4590         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4591         D3DPSREGISTER_SpecularPower = 36,
4592         D3DPSREGISTER_UserVec1 = 37,
4593         D3DPSREGISTER_UserVec2 = 38,
4594         D3DPSREGISTER_UserVec3 = 39,
4595         D3DPSREGISTER_UserVec4 = 40,
4596         D3DPSREGISTER_ViewTintColor = 41,
4597         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4598         D3DPSREGISTER_BloomColorSubtract = 43,
4599         D3DPSREGISTER_ViewToLight = 44, // float4x4
4600         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4601         D3DPSREGISTER_NormalmapScrollBlend = 52,
4602         // next at 53
4603 }
4604 D3DPSREGISTER_t;
4605
4606 /// information about each possible shader permutation
4607 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4608 /// currently selected permutation
4609 r_hlsl_permutation_t *r_hlsl_permutation;
4610 /// storage for permutations linked in the hash table
4611 memexpandablearray_t r_hlsl_permutationarray;
4612
4613 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4614 {
4615         //unsigned int hashdepth = 0;
4616         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4617         r_hlsl_permutation_t *p;
4618         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4619         {
4620                 if (p->mode == mode && p->permutation == permutation)
4621                 {
4622                         //if (hashdepth > 10)
4623                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4624                         return p;
4625                 }
4626                 //hashdepth++;
4627         }
4628         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4629         p->mode = mode;
4630         p->permutation = permutation;
4631         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4632         r_hlsl_permutationhash[mode][hashindex] = p;
4633         //if (hashdepth > 10)
4634         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4635         return p;
4636 }
4637
4638 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4639 {
4640         char *shaderstring;
4641         if (!filename || !filename[0])
4642                 return NULL;
4643         if (!strcmp(filename, "hlsl/default.hlsl"))
4644         {
4645                 if (!hlslshaderstring)
4646                 {
4647                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4648                         if (hlslshaderstring)
4649                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4650                         else
4651                                 hlslshaderstring = (char *)builtincgshaderstring;
4652                 }
4653                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4654                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4655                 return shaderstring;
4656         }
4657         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4658         if (shaderstring)
4659         {
4660                 if (printfromdisknotice)
4661                         Con_DPrintf("from disk %s... ", filename);
4662                 return shaderstring;
4663         }
4664         return shaderstring;
4665 }
4666
4667 #include <d3dx9.h>
4668 //#include <d3dx9shader.h>
4669 //#include <d3dx9mesh.h>
4670
4671 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4672 {
4673         DWORD *vsbin = NULL;
4674         DWORD *psbin = NULL;
4675         fs_offset_t vsbinsize;
4676         fs_offset_t psbinsize;
4677 //      IDirect3DVertexShader9 *vs = NULL;
4678 //      IDirect3DPixelShader9 *ps = NULL;
4679         ID3DXBuffer *vslog = NULL;
4680         ID3DXBuffer *vsbuffer = NULL;
4681         ID3DXConstantTable *vsconstanttable = NULL;
4682         ID3DXBuffer *pslog = NULL;
4683         ID3DXBuffer *psbuffer = NULL;
4684         ID3DXConstantTable *psconstanttable = NULL;
4685         int vsresult = 0;
4686         int psresult = 0;
4687         char temp[MAX_INPUTLINE];
4688         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4689         qboolean debugshader = gl_paranoid.integer != 0;
4690         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4691         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4692         if (!debugshader)
4693         {
4694                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4695                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4696         }
4697         if ((!vsbin && vertstring) || (!psbin && fragstring))
4698         {
4699                 const char* dllnames_d3dx9 [] =
4700                 {
4701                         "d3dx9_43.dll",
4702                         "d3dx9_42.dll",
4703                         "d3dx9_41.dll",
4704                         "d3dx9_40.dll",
4705                         "d3dx9_39.dll",
4706                         "d3dx9_38.dll",
4707                         "d3dx9_37.dll",
4708                         "d3dx9_36.dll",
4709                         "d3dx9_35.dll",
4710                         "d3dx9_34.dll",
4711                         "d3dx9_33.dll",
4712                         "d3dx9_32.dll",
4713                         "d3dx9_31.dll",
4714                         "d3dx9_30.dll",
4715                         "d3dx9_29.dll",
4716                         "d3dx9_28.dll",
4717                         "d3dx9_27.dll",
4718                         "d3dx9_26.dll",
4719                         "d3dx9_25.dll",
4720                         "d3dx9_24.dll",
4721                         NULL
4722                 };
4723                 dllhandle_t d3dx9_dll = NULL;
4724                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4725                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4726                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4727                 dllfunction_t d3dx9_dllfuncs[] =
4728                 {
4729                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4730                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4731                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4732                         {NULL, NULL}
4733                 };
4734                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4735                 {
4736                         DWORD shaderflags = 0;
4737                         if (debugshader)
4738                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4739                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4740                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4741                         if (vertstring && vertstring[0])
4742                         {
4743                                 if (debugshader)
4744                                 {
4745 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4746 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4747                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4748                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4749                                 }
4750                                 else
4751                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4752                                 if (vsbuffer)
4753                                 {
4754                                         vsbinsize = vsbuffer->GetBufferSize();
4755                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4756                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4757                                         vsbuffer->Release();
4758                                 }
4759                                 if (vslog)
4760                                 {
4761                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4762                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4763                                         vslog->Release();
4764                                 }
4765                         }
4766                         if (fragstring && fragstring[0])
4767                         {
4768                                 if (debugshader)
4769                                 {
4770 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4771 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4772                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4773                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4774                                 }
4775                                 else
4776                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4777                                 if (psbuffer)
4778                                 {
4779                                         psbinsize = psbuffer->GetBufferSize();
4780                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4781                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4782                                         psbuffer->Release();
4783                                 }
4784                                 if (pslog)
4785                                 {
4786                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4787                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4788                                         pslog->Release();
4789                                 }
4790                         }
4791                         Sys_UnloadLibrary(&d3dx9_dll);
4792                 }
4793                 else
4794                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4795         }
4796         if (vsbin && psbin)
4797         {
4798                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4799                 if (FAILED(vsresult))
4800                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4801                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4802                 if (FAILED(psresult))
4803                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4804         }
4805         // free the shader data
4806         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4807         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4808 }
4809
4810 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4811 {
4812         int i;
4813         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4814         int vertstring_length = 0;
4815         int geomstring_length = 0;
4816         int fragstring_length = 0;
4817         char *t;
4818         char *vertexstring, *geometrystring, *fragmentstring;
4819         char *vertstring, *geomstring, *fragstring;
4820         char permutationname[256];
4821         char cachename[256];
4822         int vertstrings_count = 0;
4823         int geomstrings_count = 0;
4824         int fragstrings_count = 0;
4825         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4826         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4827         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4828
4829         if (p->compiled)
4830                 return;
4831         p->compiled = true;
4832         p->vertexshader = NULL;
4833         p->pixelshader = NULL;
4834
4835         permutationname[0] = 0;
4836         cachename[0] = 0;
4837         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4838         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4839         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4840
4841         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4842         strlcat(cachename, "hlsl/", sizeof(cachename));
4843
4844         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4845         vertstrings_count = 0;
4846         geomstrings_count = 0;
4847         fragstrings_count = 0;
4848         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4849         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4850         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4851
4852         // the first pretext is which type of shader to compile as
4853         // (later these will all be bound together as a program object)
4854         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4855         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4856         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4857
4858         // the second pretext is the mode (for example a light source)
4859         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4860         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4861         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4862         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4863         strlcat(cachename, modeinfo->name, sizeof(cachename));
4864
4865         // now add all the permutation pretexts
4866         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4867         {
4868                 if (permutation & (1<<i))
4869                 {
4870                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4871                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4872                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4873                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4874                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4875                 }
4876                 else
4877                 {
4878                         // keep line numbers correct
4879                         vertstrings_list[vertstrings_count++] = "\n";
4880                         geomstrings_list[geomstrings_count++] = "\n";
4881                         fragstrings_list[fragstrings_count++] = "\n";
4882                 }
4883         }
4884
4885         // add static parms
4886         R_CompileShader_AddStaticParms(mode, permutation);
4887         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4888         vertstrings_count += shaderstaticparms_count;
4889         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4890         geomstrings_count += shaderstaticparms_count;
4891         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4892         fragstrings_count += shaderstaticparms_count;
4893
4894         // replace spaces in the cachename with _ characters
4895         for (i = 0;cachename[i];i++)
4896                 if (cachename[i] == ' ')
4897                         cachename[i] = '_';
4898
4899         // now append the shader text itself
4900         vertstrings_list[vertstrings_count++] = vertexstring;
4901         geomstrings_list[geomstrings_count++] = geometrystring;
4902         fragstrings_list[fragstrings_count++] = fragmentstring;
4903
4904         // if any sources were NULL, clear the respective list
4905         if (!vertexstring)
4906                 vertstrings_count = 0;
4907         if (!geometrystring)
4908                 geomstrings_count = 0;
4909         if (!fragmentstring)
4910                 fragstrings_count = 0;
4911
4912         vertstring_length = 0;
4913         for (i = 0;i < vertstrings_count;i++)
4914                 vertstring_length += strlen(vertstrings_list[i]);
4915         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4916         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4917                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4918
4919         geomstring_length = 0;
4920         for (i = 0;i < geomstrings_count;i++)
4921                 geomstring_length += strlen(geomstrings_list[i]);
4922         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4923         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4924                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4925
4926         fragstring_length = 0;
4927         for (i = 0;i < fragstrings_count;i++)
4928                 fragstring_length += strlen(fragstrings_list[i]);
4929         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4930         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4931                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4932
4933         // try to load the cached shader, or generate one
4934         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4935
4936         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4937                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4938         else
4939                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4940
4941         // free the strings
4942         if (vertstring)
4943                 Mem_Free(vertstring);
4944         if (geomstring)
4945                 Mem_Free(geomstring);
4946         if (fragstring)
4947                 Mem_Free(fragstring);
4948         if (vertexstring)
4949                 Mem_Free(vertexstring);
4950         if (geometrystring)
4951                 Mem_Free(geometrystring);
4952         if (fragmentstring)
4953                 Mem_Free(fragmentstring);
4954 }
4955
4956 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4957 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4958 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);}
4959 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);}
4960 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);}
4961 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);}
4962
4963 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4964 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4965 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);}
4966 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);}
4967 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);}
4968 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);}
4969
4970 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4971 {
4972         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4973         if (r_hlsl_permutation != perm)
4974         {
4975                 r_hlsl_permutation = perm;
4976                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4977                 {
4978                         if (!r_hlsl_permutation->compiled)
4979                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4980                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4981                         {
4982                                 // remove features until we find a valid permutation
4983                                 int i;
4984                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4985                                 {
4986                                         // reduce i more quickly whenever it would not remove any bits
4987                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4988                                         if (!(permutation & j))
4989                                                 continue;
4990                                         permutation -= j;
4991                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4992                                         if (!r_hlsl_permutation->compiled)
4993                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4994                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4995                                                 break;
4996                                 }
4997                                 if (i >= SHADERPERMUTATION_COUNT)
4998                                 {
4999                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
5000                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
5001                                         return; // no bit left to clear, entire mode is broken
5002                                 }
5003                         }
5004                 }
5005                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
5006                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
5007         }
5008         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5009         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5010         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
5011 }
5012 #endif
5013
5014 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
5015 {
5016         DPSOFTRAST_SetShader(mode, permutation);
5017         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5018         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5019         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
5020 }
5021
5022 void R_GLSL_Restart_f(void)
5023 {
5024         unsigned int i, limit;
5025         if (glslshaderstring && glslshaderstring != builtinshaderstring)
5026                 Mem_Free(glslshaderstring);
5027         glslshaderstring = NULL;
5028         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
5029                 Mem_Free(cgshaderstring);
5030         cgshaderstring = NULL;
5031         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
5032                 Mem_Free(hlslshaderstring);
5033         hlslshaderstring = NULL;
5034         switch(vid.renderpath)
5035         {
5036         case RENDERPATH_D3D9:
5037 #ifdef SUPPORTD3D
5038                 {
5039                         r_hlsl_permutation_t *p;
5040                         r_hlsl_permutation = NULL;
5041 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5042 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5043 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5044 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5045                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
5046                         for (i = 0;i < limit;i++)
5047                         {
5048                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
5049                                 {
5050                                         if (p->vertexshader)
5051                                                 IDirect3DVertexShader9_Release(p->vertexshader);
5052                                         if (p->pixelshader)
5053                                                 IDirect3DPixelShader9_Release(p->pixelshader);
5054                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
5055                                 }
5056                         }
5057                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
5058                 }
5059 #endif
5060                 break;
5061         case RENDERPATH_D3D10:
5062                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5063                 break;
5064         case RENDERPATH_D3D11:
5065                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5066                 break;
5067         case RENDERPATH_GL20:
5068         case RENDERPATH_GLES2:
5069                 {
5070                         r_glsl_permutation_t *p;
5071                         r_glsl_permutation = NULL;
5072                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5073                         for (i = 0;i < limit;i++)
5074                         {
5075                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5076                                 {
5077                                         GL_Backend_FreeProgram(p->program);
5078                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5079                                 }
5080                         }
5081                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5082                 }
5083                 break;
5084         case RENDERPATH_CGGL:
5085 #ifdef SUPPORTCG
5086                 {
5087                         r_cg_permutation_t *p;
5088                         r_cg_permutation = NULL;
5089                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5090                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5091                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5092                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5093                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5094                         for (i = 0;i < limit;i++)
5095                         {
5096                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5097                                 {
5098                                         if (p->vprogram)
5099                                                 cgDestroyProgram(p->vprogram);
5100                                         if (p->fprogram)
5101                                                 cgDestroyProgram(p->fprogram);
5102                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5103                                 }
5104                         }
5105                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5106                 }
5107 #endif
5108                 break;
5109         case RENDERPATH_GL13:
5110         case RENDERPATH_GL11:
5111                 break;
5112         case RENDERPATH_SOFT:
5113                 break;
5114         }
5115 }
5116
5117 void R_GLSL_DumpShader_f(void)
5118 {
5119         int i;
5120         qfile_t *file;
5121
5122         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5123         if (file)
5124         {
5125                 FS_Print(file, "/* The engine may define the following macros:\n");
5126                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5127                 for (i = 0;i < SHADERMODE_COUNT;i++)
5128                         FS_Print(file, glslshadermodeinfo[i].pretext);
5129                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5130                         FS_Print(file, shaderpermutationinfo[i].pretext);
5131                 FS_Print(file, "*/\n");
5132                 FS_Print(file, builtinshaderstring);
5133                 FS_Close(file);
5134                 Con_Printf("glsl/default.glsl written\n");
5135         }
5136         else
5137                 Con_Printf("failed to write to glsl/default.glsl\n");
5138
5139 #ifdef SUPPORTCG
5140         file = FS_OpenRealFile("cg/default.cg", "w", false);
5141         if (file)
5142         {
5143                 FS_Print(file, "/* The engine may define the following macros:\n");
5144                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5145                 for (i = 0;i < SHADERMODE_COUNT;i++)
5146                         FS_Print(file, cgshadermodeinfo[i].pretext);
5147                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5148                         FS_Print(file, shaderpermutationinfo[i].pretext);
5149                 FS_Print(file, "*/\n");
5150                 FS_Print(file, builtincgshaderstring);
5151                 FS_Close(file);
5152                 Con_Printf("cg/default.cg written\n");
5153         }
5154         else
5155                 Con_Printf("failed to write to cg/default.cg\n");
5156 #endif
5157
5158         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5159         if (file)
5160         {
5161                 FS_Print(file, "/* The engine may define the following macros:\n");
5162                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5163                 for (i = 0;i < SHADERMODE_COUNT;i++)
5164                         FS_Print(file, hlslshadermodeinfo[i].pretext);
5165                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5166                         FS_Print(file, shaderpermutationinfo[i].pretext);
5167                 FS_Print(file, "*/\n");
5168                 FS_Print(file, builtincgshaderstring);
5169                 FS_Close(file);
5170                 Con_Printf("hlsl/default.hlsl written\n");
5171         }
5172         else
5173                 Con_Printf("failed to write to hlsl/default.hlsl\n");
5174 }
5175
5176 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5177 {
5178         if (!second)
5179                 texturemode = GL_MODULATE;
5180         switch (vid.renderpath)
5181         {
5182         case RENDERPATH_D3D9:
5183 #ifdef SUPPORTD3D
5184                 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))));
5185                 R_Mesh_TexBind(GL20TU_FIRST , first );
5186                 R_Mesh_TexBind(GL20TU_SECOND, second);
5187 #endif
5188                 break;
5189         case RENDERPATH_D3D10:
5190                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5191                 break;
5192         case RENDERPATH_D3D11:
5193                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5194                 break;
5195         case RENDERPATH_GL20:
5196         case RENDERPATH_GLES2:
5197                 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))));
5198                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
5199                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
5200                 break;
5201         case RENDERPATH_CGGL:
5202 #ifdef SUPPORTCG
5203                 CHECKCGERROR
5204                 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5205                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5206                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5207 #endif
5208                 break;
5209         case RENDERPATH_GL13:
5210                 R_Mesh_TexBind(0, first );
5211                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5212                 R_Mesh_TexBind(1, second);
5213                 if (second)
5214                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5215                 break;
5216         case RENDERPATH_GL11:
5217                 R_Mesh_TexBind(0, first );
5218                 break;
5219         case RENDERPATH_SOFT:
5220                 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))));
5221                 R_Mesh_TexBind(GL20TU_FIRST , first );
5222                 R_Mesh_TexBind(GL20TU_SECOND, second);
5223                 break;
5224         }
5225 }
5226
5227 void R_SetupShader_DepthOrShadow(void)
5228 {
5229         switch (vid.renderpath)
5230         {
5231         case RENDERPATH_D3D9:
5232 #ifdef SUPPORTD3D
5233                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5234 #endif
5235                 break;
5236         case RENDERPATH_D3D10:
5237                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5238                 break;
5239         case RENDERPATH_D3D11:
5240                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5241                 break;
5242         case RENDERPATH_GL20:
5243         case RENDERPATH_GLES2:
5244                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5245                 break;
5246         case RENDERPATH_CGGL:
5247 #ifdef SUPPORTCG
5248                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5249 #endif
5250                 break;
5251         case RENDERPATH_GL13:
5252                 R_Mesh_TexBind(0, 0);
5253                 R_Mesh_TexBind(1, 0);
5254                 break;
5255         case RENDERPATH_GL11:
5256                 R_Mesh_TexBind(0, 0);
5257                 break;
5258         case RENDERPATH_SOFT:
5259                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
5260                 break;
5261         }
5262 }
5263
5264 void R_SetupShader_ShowDepth(void)
5265 {
5266         switch (vid.renderpath)
5267         {
5268         case RENDERPATH_D3D9:
5269 #ifdef SUPPORTHLSL
5270                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5271 #endif
5272                 break;
5273         case RENDERPATH_D3D10:
5274                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5275                 break;
5276         case RENDERPATH_D3D11:
5277                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5278                 break;
5279         case RENDERPATH_GL20:
5280         case RENDERPATH_GLES2:
5281                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5282                 break;
5283         case RENDERPATH_CGGL:
5284 #ifdef SUPPORTCG
5285                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5286 #endif
5287                 break;
5288         case RENDERPATH_GL13:
5289                 break;
5290         case RENDERPATH_GL11:
5291                 break;
5292         case RENDERPATH_SOFT:
5293                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
5294                 break;
5295         }
5296 }
5297
5298 extern qboolean r_shadow_usingdeferredprepass;
5299 extern cvar_t r_shadow_deferred_8bitrange;
5300 extern rtexture_t *r_shadow_attenuationgradienttexture;
5301 extern rtexture_t *r_shadow_attenuation2dtexture;
5302 extern rtexture_t *r_shadow_attenuation3dtexture;
5303 extern qboolean r_shadow_usingshadowmap2d;
5304 extern qboolean r_shadow_usingshadowmaportho;
5305 extern float r_shadow_shadowmap_texturescale[2];
5306 extern float r_shadow_shadowmap_parameters[4];
5307 extern qboolean r_shadow_shadowmapvsdct;
5308 extern qboolean r_shadow_shadowmapsampler;
5309 extern int r_shadow_shadowmappcf;
5310 extern rtexture_t *r_shadow_shadowmap2dtexture;
5311 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5312 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5313 extern matrix4x4_t r_shadow_shadowmapmatrix;
5314 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5315 extern int r_shadow_prepass_width;
5316 extern int r_shadow_prepass_height;
5317 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5318 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5319 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5320 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5321 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5322 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5323 {
5324         // a blendfunc allows colormod if:
5325         // a) it can never keep the destination pixel invariant, or
5326         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5327         // this is to prevent unintended side effects from colormod
5328
5329         // in formulas:
5330         // IF there is a (s, sa) for which for all (d, da),
5331         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5332         // THEN, for this (s, sa) and all (colormod, d, da):
5333         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5334         // OBVIOUSLY, this means that
5335         //   s*colormod * src(s*colormod, d, sa, da) = 0
5336         //   dst(s*colormod, d, sa, da)              = 1
5337
5338         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5339
5340         // main condition to leave dst color invariant:
5341         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5342         //   src == GL_ZERO:
5343         //     s * 0 + d * dst(s, d, sa, da) == d
5344         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5345         //       => colormod is a problem for GL_SRC_COLOR only
5346         //   src == GL_ONE:
5347         //     s + d * dst(s, d, sa, da) == d
5348         //       => s == 0
5349         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5350         //       => colormod is never problematic for these
5351         //   src == GL_SRC_COLOR:
5352         //     s*s + d * dst(s, d, sa, da) == d
5353         //       => s == 0
5354         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5355         //       => colormod is never problematic for these
5356         //   src == GL_ONE_MINUS_SRC_COLOR:
5357         //     s*(1-s) + d * dst(s, d, sa, da) == d
5358         //       => s == 0 or s == 1
5359         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5360         //       => colormod is a problem for GL_SRC_COLOR only
5361         //   src == GL_DST_COLOR
5362         //     s*d + d * dst(s, d, sa, da) == d
5363         //       => s == 1
5364         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5365         //       => colormod is always a problem
5366         //     or
5367         //       => s == 0
5368         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5369         //       => colormod is never problematic for these
5370         //       => BUT, we do not know s! We must assume it is problematic
5371         //       then... except in GL_ONE case, where we know all invariant
5372         //       cases are fine
5373         //   src == GL_ONE_MINUS_DST_COLOR
5374         //     s*(1-d) + d * dst(s, d, sa, da) == d
5375         //       => s == 0 (1-d is impossible to handle for our desired result)
5376         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5377         //       => colormod is never problematic for these
5378         //   src == GL_SRC_ALPHA
5379         //     s*sa + d * dst(s, d, sa, da) == d
5380         //       => s == 0, or sa == 0
5381         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5382         //       => colormod breaks in the case GL_SRC_COLOR only
5383         //   src == GL_ONE_MINUS_SRC_ALPHA
5384         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5385         //       => s == 0, or sa == 1
5386         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5387         //       => colormod breaks in the case GL_SRC_COLOR only
5388         //   src == GL_DST_ALPHA
5389         //     s*da + d * dst(s, d, sa, da) == d
5390         //       => s == 0
5391         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5392         //       => colormod is never problematic for these
5393
5394         switch(src)
5395         {
5396                 case GL_ZERO:
5397                 case GL_ONE_MINUS_SRC_COLOR:
5398                 case GL_SRC_ALPHA:
5399                 case GL_ONE_MINUS_SRC_ALPHA:
5400                         if(dst == GL_SRC_COLOR)
5401                                 return false;
5402                         return true;
5403                 case GL_ONE:
5404                 case GL_SRC_COLOR:
5405                 case GL_ONE_MINUS_DST_COLOR:
5406                 case GL_DST_ALPHA:
5407                 case GL_ONE_MINUS_DST_ALPHA:
5408                         return true;
5409                 case GL_DST_COLOR:
5410                         if(dst == GL_ONE)
5411                                 return true;
5412                         return false;
5413                 default:
5414                         return false;
5415         }
5416 }
5417 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)
5418 {
5419         // select a permutation of the lighting shader appropriate to this
5420         // combination of texture, entity, light source, and fogging, only use the
5421         // minimum features necessary to avoid wasting rendering time in the
5422         // fragment shader on features that are not being used
5423         unsigned int permutation = 0;
5424         unsigned int mode = 0;
5425         qboolean allow_colormod;
5426         static float dummy_colormod[3] = {1, 1, 1};
5427         float *colormod = rsurface.colormod;
5428         float m16f[16];
5429         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5430         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5431                 permutation |= SHADERPERMUTATION_ALPHAKILL;
5432         if (rsurfacepass == RSURFPASS_BACKGROUND)
5433         {
5434                 // distorted background
5435                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5436                 {
5437                         mode = SHADERMODE_WATER;
5438                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5439                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5440                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
5441                         {
5442                                 // this is the right thing to do for wateralpha
5443                                 GL_BlendFunc(GL_ONE, GL_ZERO);
5444                                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5445                         }
5446                         else
5447                         {
5448                                 // this is the right thing to do for entity alpha
5449                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5450                                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5451                         }
5452                 }
5453                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5454                 {
5455                         mode = SHADERMODE_REFRACTION;
5456                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5457                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5458                 }
5459                 else
5460                 {
5461                         mode = SHADERMODE_GENERIC;
5462                         permutation |= SHADERPERMUTATION_DIFFUSE;
5463                         GL_BlendFunc(GL_ONE, GL_ZERO);
5464                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5465                 }
5466         }
5467         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5468         {
5469                 if (r_glsl_offsetmapping.integer)
5470                 {
5471                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5472                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5473                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5474                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5475                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5476                         {
5477                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5478                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5479                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5480                         }
5481                 }
5482                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5483                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5484                 // normalmap (deferred prepass), may use alpha test on diffuse
5485                 mode = SHADERMODE_DEFERREDGEOMETRY;
5486                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5487                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5488                 GL_BlendFunc(GL_ONE, GL_ZERO);
5489                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5490         }
5491         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5492         {
5493                 if (r_glsl_offsetmapping.integer)
5494                 {
5495                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5496                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5497                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5498                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5499                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5500                         {
5501                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5502                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5503                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5504                         }
5505                 }
5506                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5507                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5508                 // light source
5509                 mode = SHADERMODE_LIGHTSOURCE;
5510                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5511                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5512                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5513                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5514                 if (diffusescale > 0)
5515                         permutation |= SHADERPERMUTATION_DIFFUSE;
5516                 if (specularscale > 0)
5517                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5518                 if (r_refdef.fogenabled)
5519                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5520                 if (rsurface.texture->colormapping)
5521                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5522                 if (r_shadow_usingshadowmap2d)
5523                 {
5524                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5525                         if(r_shadow_shadowmapvsdct)
5526                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5527
5528                         if (r_shadow_shadowmapsampler)
5529                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5530                         if (r_shadow_shadowmappcf > 1)
5531                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5532                         else if (r_shadow_shadowmappcf)
5533                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5534                 }
5535                 if (rsurface.texture->reflectmasktexture)
5536                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5537                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5538                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5539         }
5540         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5541         {
5542                 if (r_glsl_offsetmapping.integer)
5543                 {
5544                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5545                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5546                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5547                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5548                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5549                         {
5550                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5551                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5552                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5553                         }
5554                 }
5555                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5556                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5557                 // unshaded geometry (fullbright or ambient model lighting)
5558                 mode = SHADERMODE_FLATCOLOR;
5559                 ambientscale = diffusescale = specularscale = 0;
5560                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5561                         permutation |= SHADERPERMUTATION_GLOW;
5562                 if (r_refdef.fogenabled)
5563                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5564                 if (rsurface.texture->colormapping)
5565                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5566                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5567                 {
5568                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5569                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5570
5571                         if (r_shadow_shadowmapsampler)
5572                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5573                         if (r_shadow_shadowmappcf > 1)
5574                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5575                         else if (r_shadow_shadowmappcf)
5576                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5577                 }
5578                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5579                         permutation |= SHADERPERMUTATION_REFLECTION;
5580                 if (rsurface.texture->reflectmasktexture)
5581                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5582                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5583                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5584         }
5585         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5586         {
5587                 if (r_glsl_offsetmapping.integer)
5588                 {
5589                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5590                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5591                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5592                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5593                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5594                         {
5595                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5596                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5597                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5598                         }
5599                 }
5600                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5601                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5602                 // directional model lighting
5603                 mode = SHADERMODE_LIGHTDIRECTION;
5604                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5605                         permutation |= SHADERPERMUTATION_GLOW;
5606                 permutation |= SHADERPERMUTATION_DIFFUSE;
5607                 if (specularscale > 0)
5608                         permutation |= SHADERPERMUTATION_SPECULAR;
5609                 if (r_refdef.fogenabled)
5610                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5611                 if (rsurface.texture->colormapping)
5612                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5613                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5614                 {
5615                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5616                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5617
5618                         if (r_shadow_shadowmapsampler)
5619                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5620                         if (r_shadow_shadowmappcf > 1)
5621                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5622                         else if (r_shadow_shadowmappcf)
5623                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5624                 }
5625                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5626                         permutation |= SHADERPERMUTATION_REFLECTION;
5627                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5628                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5629                 if (rsurface.texture->reflectmasktexture)
5630                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5631                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5632                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5633         }
5634         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5635         {
5636                 if (r_glsl_offsetmapping.integer)
5637                 {
5638                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5639                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5640                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5641                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5642                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5643                         {
5644                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5645                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5646                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5647                         }
5648                 }
5649                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5650                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5651                 // ambient model lighting
5652                 mode = SHADERMODE_LIGHTDIRECTION;
5653                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5654                         permutation |= SHADERPERMUTATION_GLOW;
5655                 if (r_refdef.fogenabled)
5656                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5657                 if (rsurface.texture->colormapping)
5658                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5659                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5660                 {
5661                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5662                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5663
5664                         if (r_shadow_shadowmapsampler)
5665                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5666                         if (r_shadow_shadowmappcf > 1)
5667                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5668                         else if (r_shadow_shadowmappcf)
5669                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5670                 }
5671                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5672                         permutation |= SHADERPERMUTATION_REFLECTION;
5673                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5674                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5675                 if (rsurface.texture->reflectmasktexture)
5676                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5677                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5678                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5679         }
5680         else
5681         {
5682                 if (r_glsl_offsetmapping.integer)
5683                 {
5684                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5685                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5686                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5687                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5688                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5689                         {
5690                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5691                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5692                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5693                         }
5694                 }
5695                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5696                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5697                 // lightmapped wall
5698                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5699                         permutation |= SHADERPERMUTATION_GLOW;
5700                 if (r_refdef.fogenabled)
5701                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5702                 if (rsurface.texture->colormapping)
5703                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5704                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5705                 {
5706                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5707                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5708
5709                         if (r_shadow_shadowmapsampler)
5710                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5711                         if (r_shadow_shadowmappcf > 1)
5712                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5713                         else if (r_shadow_shadowmappcf)
5714                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5715                 }
5716                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5717                         permutation |= SHADERPERMUTATION_REFLECTION;
5718                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5719                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5720                 if (rsurface.texture->reflectmasktexture)
5721                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5722                 if (FAKELIGHT_ENABLED)
5723                 {
5724                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5725                         mode = SHADERMODE_FAKELIGHT;
5726                         permutation |= SHADERPERMUTATION_DIFFUSE;
5727                         if (specularscale > 0)
5728                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5729                 }
5730                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5731                 {
5732                         // deluxemapping (light direction texture)
5733                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5734                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5735                         else
5736                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5737                         permutation |= SHADERPERMUTATION_DIFFUSE;
5738                         if (specularscale > 0)
5739                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5740                 }
5741                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5742                 {
5743                         // fake deluxemapping (uniform light direction in tangentspace)
5744                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5745                         permutation |= SHADERPERMUTATION_DIFFUSE;
5746                         if (specularscale > 0)
5747                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5748                 }
5749                 else if (rsurface.uselightmaptexture)
5750                 {
5751                         // ordinary lightmapping (q1bsp, q3bsp)
5752                         mode = SHADERMODE_LIGHTMAP;
5753                 }
5754                 else
5755                 {
5756                         // ordinary vertex coloring (q3bsp)
5757                         mode = SHADERMODE_VERTEXCOLOR;
5758                 }
5759                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5760                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5761         }
5762         if(!allow_colormod)
5763                 colormod = dummy_colormod;
5764         switch(vid.renderpath)
5765         {
5766         case RENDERPATH_D3D9:
5767 #ifdef SUPPORTD3D
5768                 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);
5769                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5770                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5771                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5772                 if (mode == SHADERMODE_LIGHTSOURCE)
5773                 {
5774                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5775                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5776                 }
5777                 else
5778                 {
5779                         if (mode == SHADERMODE_LIGHTDIRECTION)
5780                         {
5781                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5782                         }
5783                 }
5784                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5785                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5786                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5787                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5788                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5789
5790                 if (mode == SHADERMODE_LIGHTSOURCE)
5791                 {
5792                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5793                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5794                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5795                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5796                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5797
5798                         // additive passes are only darkened by fog, not tinted
5799                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5800                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5801                 }
5802                 else
5803                 {
5804                         if (mode == SHADERMODE_FLATCOLOR)
5805                         {
5806                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5807                         }
5808                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5809                         {
5810                                 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]);
5811                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5812                                 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);
5813                                 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);
5814                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5815                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5816                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5817                         }
5818                         else
5819                         {
5820                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5821                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5822                                 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);
5823                                 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);
5824                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5825                         }
5826                         // additive passes are only darkened by fog, not tinted
5827                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5828                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5829                         else
5830                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5831                         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);
5832                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5833                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5834                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5835                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5836                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5837                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5838                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5839                         if (mode == SHADERMODE_WATER)
5840                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5841                 }
5842                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5843                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5844                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5845                 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));
5846                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5847                 if (rsurface.texture->pantstexture)
5848                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5849                 else
5850                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5851                 if (rsurface.texture->shirttexture)
5852                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5853                 else
5854                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5855                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5856                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5857                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5858                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5859                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5860                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5861                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5862
5863                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5864                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5865                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5866                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5867                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5868                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5869                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5870                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5871                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5872                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5873                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5874                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5875                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5876                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5877                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5878                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5879                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5880                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5881                 {
5882                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5883                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5884                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5885                 }
5886                 else
5887                 {
5888                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5889                 }
5890 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5891 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5892                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5893                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5894                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5895                 {
5896                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5897                         if (rsurface.rtlight)
5898                         {
5899                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5900                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5901                         }
5902                 }
5903 #endif
5904                 break;
5905         case RENDERPATH_D3D10:
5906                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5907                 break;
5908         case RENDERPATH_D3D11:
5909                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5910                 break;
5911         case RENDERPATH_GL20:
5912         case RENDERPATH_GLES2:
5913                 if (!vid.useinterleavedarrays)
5914                 {
5915                         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);
5916                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5917                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5918                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5919                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5920                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5921                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5922                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5923                 }
5924                 else
5925                 {
5926                         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);
5927                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5928                 }
5929                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5930                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5931                 if (mode == SHADERMODE_LIGHTSOURCE)
5932                 {
5933                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5934                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5935                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5936                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5937                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5938                         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);
5939         
5940                         // additive passes are only darkened by fog, not tinted
5941                         if (r_glsl_permutation->loc_FogColor >= 0)
5942                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5943                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5944                 }
5945                 else
5946                 {
5947                         if (mode == SHADERMODE_FLATCOLOR)
5948                         {
5949                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5950                         }
5951                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5952                         {
5953                                 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]);
5954                                 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]);
5955                                 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);
5956                                 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);
5957                                 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);
5958                                 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]);
5959                                 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]);
5960                         }
5961                         else
5962                         {
5963                                 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]);
5964                                 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]);
5965                                 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);
5966                                 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);
5967                                 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);
5968                         }
5969                         // additive passes are only darkened by fog, not tinted
5970                         if (r_glsl_permutation->loc_FogColor >= 0)
5971                         {
5972                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5973                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5974                                 else
5975                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5976                         }
5977                         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);
5978                         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]);
5979                         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]);
5980                         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]);
5981                         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]);
5982                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5983                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5984                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5985                         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]);
5986                 }
5987                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5988                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5989                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5990                 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]);
5991                 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]);
5992
5993                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5994                 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));
5995                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5996                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5997                 {
5998                         if (rsurface.texture->pantstexture)
5999                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6000                         else
6001                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
6002                 }
6003                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
6004                 {
6005                         if (rsurface.texture->shirttexture)
6006                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6007                         else
6008                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
6009                 }
6010                 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]);
6011                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
6012                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
6013                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
6014                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
6015                 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]);
6016                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6017
6018                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
6019                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
6020                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
6021                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
6022                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
6023                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
6024                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
6025                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
6026                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
6027                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
6028                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
6029                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
6030                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
6031                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
6032                 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);
6033                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
6034                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
6035                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
6036                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
6037                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
6038                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6039                 {
6040                         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);
6041                         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);
6042                         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);
6043                 }
6044                 else
6045                 {
6046                         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);
6047                 }
6048                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
6049                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
6050                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
6051                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
6052                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6053                 {
6054                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
6055                         if (rsurface.rtlight)
6056                         {
6057                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
6058                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
6059                         }
6060                 }
6061                 CHECKGLERROR
6062                 break;
6063         case RENDERPATH_CGGL:
6064 #ifdef SUPPORTCG
6065                 if (!vid.useinterleavedarrays)
6066                 {
6067                         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);
6068                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
6069                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
6070                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
6071                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
6072                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6073                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6074                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6075                 }
6076                 else
6077                 {
6078                         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);
6079                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6080                 }
6081                 R_SetupShader_SetPermutationCG(mode, permutation);
6082                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6083                 if (mode == SHADERMODE_LIGHTSOURCE)
6084                 {
6085                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6086                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6087                 }
6088                 else
6089                 {
6090                         if (mode == SHADERMODE_LIGHTDIRECTION)
6091                         {
6092                                 if (r_cg_permutation->vp_LightDir) cgGLSetParameter3f(r_cg_permutation->vp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
6093                         }
6094                 }
6095                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6096                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6097                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6098                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6099                 if (r_cg_permutation->vp_FogPlane) cgGLSetParameter4f(r_cg_permutation->vp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
6100                 CHECKGLERROR
6101
6102                 if (mode == SHADERMODE_LIGHTSOURCE)
6103                 {
6104                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6105                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6106                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6107                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6108                         if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);CHECKCGERROR
6109
6110                         // additive passes are only darkened by fog, not tinted
6111                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6112                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6113                 }
6114                 else
6115                 {
6116                         if (mode == SHADERMODE_FLATCOLOR)
6117                         {
6118                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6119                         }
6120                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6121                         {
6122                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);CHECKCGERROR
6123                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);CHECKCGERROR
6124                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
6125                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6126                                 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6127                                 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);CHECKCGERROR
6128                                 if (r_cg_permutation->fp_LightDir) cgGLSetParameter3f(r_cg_permutation->fp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
6129                         }
6130                         else
6131                         {
6132                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);CHECKCGERROR
6133                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);CHECKCGERROR
6134                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
6135                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6136                                 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6137                         }
6138                         // additive passes are only darkened by fog, not tinted
6139                         if (r_cg_permutation->fp_FogColor)
6140                         {
6141                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6142                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6143                                 else
6144                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6145                                 CHECKCGERROR
6146                         }
6147                         if (r_cg_permutation->fp_DistortScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);CHECKCGERROR
6148                         if (r_cg_permutation->fp_ScreenScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);CHECKCGERROR
6149                         if (r_cg_permutation->fp_ScreenCenterRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);CHECKCGERROR
6150                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4f(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR
6151                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4f(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR
6152                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6153                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6154                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6155                         if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6156                 }
6157                 if (r_cg_permutation->fp_ShadowMap_TextureScale) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
6158                 if (r_cg_permutation->fp_ShadowMap_Parameters) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
6159                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6160                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));CHECKCGERROR
6161                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6162                 if (r_cg_permutation->fp_Color_Pants)
6163                 {
6164                         if (rsurface.texture->pantstexture)
6165                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6166                         else
6167                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6168                         CHECKCGERROR
6169                 }
6170                 if (r_cg_permutation->fp_Color_Shirt)
6171                 {
6172                         if (rsurface.texture->shirttexture)
6173                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6174                         else
6175                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6176                         CHECKCGERROR
6177                 }
6178                 if (r_cg_permutation->fp_FogPlane) cgGLSetParameter4f(r_cg_permutation->fp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
6179                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6180                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6181                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6182                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6183                 if (r_cg_permutation->fp_ScreenToDepth) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
6184                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6185
6186         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
6187         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
6188         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
6189                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
6190                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
6191                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
6192                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
6193                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
6194                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
6195                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
6196                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
6197                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
6198                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
6199                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
6200                 if (r_cg_permutation->fp_Texture_ReflectCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectCube    , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);CHECKCGERROR
6201                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
6202                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
6203                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6204                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6205                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6206                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6207                 {
6208                         if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);CHECKCGERROR
6209                         else if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);CHECKCGERROR
6210                         if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);CHECKCGERROR
6211                 }
6212                 else
6213                 {
6214                         if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);CHECKCGERROR
6215                 }
6216                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6217                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6218                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6219                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6220                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6221                 {
6222                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6223                         if (rsurface.rtlight)
6224                         {
6225                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6226                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6227                         }
6228                 }
6229
6230                 CHECKGLERROR
6231 #endif
6232                 break;
6233         case RENDERPATH_GL13:
6234         case RENDERPATH_GL11:
6235                 break;
6236         case RENDERPATH_SOFT:
6237                 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);
6238                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
6239                 R_SetupShader_SetPermutationSoft(mode, permutation);
6240                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
6241                 if (mode == SHADERMODE_LIGHTSOURCE)
6242                 {
6243                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
6244                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
6245                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
6246                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
6247                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
6248                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
6249         
6250                         // additive passes are only darkened by fog, not tinted
6251                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
6252                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6253                 }
6254                 else
6255                 {
6256                         if (mode == SHADERMODE_FLATCOLOR)
6257                         {
6258                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
6259                         }
6260                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6261                         {
6262                                 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]);
6263                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
6264                                 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);
6265                                 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);
6266                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
6267                                 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]);
6268                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
6269                         }
6270                         else
6271                         {
6272                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
6273                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
6274                                 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);
6275                                 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);
6276                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
6277                         }
6278                         // additive passes are only darkened by fog, not tinted
6279                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6280                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
6281                         else
6282                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6283                         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);
6284                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
6285                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
6286                         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]);
6287                         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]);
6288                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
6289                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
6290                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6291                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6292                 }
6293                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
6294                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
6295                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
6296                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6297                 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]);
6298
6299                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
6300                 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));
6301                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
6302                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
6303                 {
6304                         if (rsurface.texture->pantstexture)
6305                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6306                         else
6307                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
6308                 }
6309                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
6310                 {
6311                         if (rsurface.texture->shirttexture)
6312                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6313                         else
6314                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
6315                 }
6316                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
6317                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
6318                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
6319                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
6320                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
6321                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6322                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6323
6324                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
6325                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
6326                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
6327                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
6328                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
6329                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
6330                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
6331                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
6332                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
6333                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
6334                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
6335                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
6336                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
6337                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
6338                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
6339                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
6340                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
6341                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6342                 {
6343                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
6344                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
6345                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6346                 }
6347                 else
6348                 {
6349                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6350                 }
6351 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
6352 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
6353                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
6354                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
6355                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6356                 {
6357                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
6358                         if (rsurface.rtlight)
6359                         {
6360                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
6361                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
6362                         }
6363                 }
6364                 break;
6365         }
6366 }
6367
6368 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6369 {
6370         // select a permutation of the lighting shader appropriate to this
6371         // combination of texture, entity, light source, and fogging, only use the
6372         // minimum features necessary to avoid wasting rendering time in the
6373         // fragment shader on features that are not being used
6374         unsigned int permutation = 0;
6375         unsigned int mode = 0;
6376         const float *lightcolorbase = rtlight->currentcolor;
6377         float ambientscale = rtlight->ambientscale;
6378         float diffusescale = rtlight->diffusescale;
6379         float specularscale = rtlight->specularscale;
6380         // this is the location of the light in view space
6381         vec3_t viewlightorigin;
6382         // this transforms from view space (camera) to light space (cubemap)
6383         matrix4x4_t viewtolight;
6384         matrix4x4_t lighttoview;
6385         float viewtolight16f[16];
6386         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6387         // light source
6388         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6389         if (rtlight->currentcubemap != r_texture_whitecube)
6390                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6391         if (diffusescale > 0)
6392                 permutation |= SHADERPERMUTATION_DIFFUSE;
6393         if (specularscale > 0)
6394                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6395         if (r_shadow_usingshadowmap2d)
6396         {
6397                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6398                 if (r_shadow_shadowmapvsdct)
6399                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6400
6401                 if (r_shadow_shadowmapsampler)
6402                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6403                 if (r_shadow_shadowmappcf > 1)
6404                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6405                 else if (r_shadow_shadowmappcf)
6406                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6407         }
6408         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6409         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6410         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6411         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6412         switch(vid.renderpath)
6413         {
6414         case RENDERPATH_D3D9:
6415 #ifdef SUPPORTD3D
6416                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6417                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6418                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6419                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6420                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6421                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6422                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6423                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6424                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6425                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6426                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6427
6428                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6429                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
6430                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6431                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6432                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
6433                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6434 #endif
6435                 break;
6436         case RENDERPATH_D3D10:
6437                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6438                 break;
6439         case RENDERPATH_D3D11:
6440                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6441                 break;
6442         case RENDERPATH_GL20:
6443         case RENDERPATH_GLES2:
6444                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6445                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6446                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6447                 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);
6448                 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);
6449                 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);
6450                 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]);
6451                 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]);
6452                 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));
6453                 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]);
6454                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
6455
6456                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
6457                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
6458                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
6459                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
6460                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
6461                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
6462                 break;
6463         case RENDERPATH_CGGL:
6464 #ifdef SUPPORTCG
6465                 R_SetupShader_SetPermutationCG(mode, permutation);
6466                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6467                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6468                 if (r_cg_permutation->fp_DeferredColor_Ambient    ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);CHECKCGERROR
6469                 if (r_cg_permutation->fp_DeferredColor_Diffuse    ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);CHECKCGERROR
6470                 if (r_cg_permutation->fp_DeferredColor_Specular   ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);CHECKCGERROR
6471                 if (r_cg_permutation->fp_ShadowMap_TextureScale   ) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
6472                 if (r_cg_permutation->fp_ShadowMap_Parameters     ) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
6473                 if (r_cg_permutation->fp_SpecularPower            ) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6474                 if (r_cg_permutation->fp_ScreenToDepth            ) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
6475                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6476
6477                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6478                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6479                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6480                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6481                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6482                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6483 #endif
6484                 break;
6485         case RENDERPATH_GL13:
6486         case RENDERPATH_GL11:
6487                 break;
6488         case RENDERPATH_SOFT:
6489                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6490                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6491                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
6492                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6493                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6494                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6495                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6496                 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]);
6497                 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));
6498                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6499                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6500
6501                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6502                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6503                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6504                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6505                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6506                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6507                 break;
6508         }
6509 }
6510
6511 #define SKINFRAME_HASH 1024
6512
6513 typedef struct
6514 {
6515         int loadsequence; // incremented each level change
6516         memexpandablearray_t array;
6517         skinframe_t *hash[SKINFRAME_HASH];
6518 }
6519 r_skinframe_t;
6520 r_skinframe_t r_skinframe;
6521
6522 void R_SkinFrame_PrepareForPurge(void)
6523 {
6524         r_skinframe.loadsequence++;
6525         // wrap it without hitting zero
6526         if (r_skinframe.loadsequence >= 200)
6527                 r_skinframe.loadsequence = 1;
6528 }
6529
6530 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6531 {
6532         if (!skinframe)
6533                 return;
6534         // mark the skinframe as used for the purging code
6535         skinframe->loadsequence = r_skinframe.loadsequence;
6536 }
6537
6538 void R_SkinFrame_Purge(void)
6539 {
6540         int i;
6541         skinframe_t *s;
6542         for (i = 0;i < SKINFRAME_HASH;i++)
6543         {
6544                 for (s = r_skinframe.hash[i];s;s = s->next)
6545                 {
6546                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6547                         {
6548                                 if (s->merged == s->base)
6549                                         s->merged = NULL;
6550                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6551                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6552                                 R_PurgeTexture(s->merged);s->merged = NULL;
6553                                 R_PurgeTexture(s->base  );s->base   = NULL;
6554                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6555                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6556                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6557                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6558                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6559                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6560                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6561                                 s->loadsequence = 0;
6562                         }
6563                 }
6564         }
6565 }
6566
6567 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6568         skinframe_t *item;
6569         char basename[MAX_QPATH];
6570
6571         Image_StripImageExtension(name, basename, sizeof(basename));
6572
6573         if( last == NULL ) {
6574                 int hashindex;
6575                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6576                 item = r_skinframe.hash[hashindex];
6577         } else {
6578                 item = last->next;
6579         }
6580
6581         // linearly search through the hash bucket
6582         for( ; item ; item = item->next ) {
6583                 if( !strcmp( item->basename, basename ) ) {
6584                         return item;
6585                 }
6586         }
6587         return NULL;
6588 }
6589
6590 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6591 {
6592         skinframe_t *item;
6593         int hashindex;
6594         char basename[MAX_QPATH];
6595
6596         Image_StripImageExtension(name, basename, sizeof(basename));
6597
6598         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6599         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6600                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6601                         break;
6602
6603         if (!item) {
6604                 rtexture_t *dyntexture;
6605                 // check whether its a dynamic texture
6606                 dyntexture = CL_GetDynTexture( basename );
6607                 if (!add && !dyntexture)
6608                         return NULL;
6609                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6610                 memset(item, 0, sizeof(*item));
6611                 strlcpy(item->basename, basename, sizeof(item->basename));
6612                 item->base = dyntexture; // either NULL or dyntexture handle
6613                 item->textureflags = textureflags;
6614                 item->comparewidth = comparewidth;
6615                 item->compareheight = compareheight;
6616                 item->comparecrc = comparecrc;
6617                 item->next = r_skinframe.hash[hashindex];
6618                 r_skinframe.hash[hashindex] = item;
6619         }
6620         else if( item->base == NULL )
6621         {
6622                 rtexture_t *dyntexture;
6623                 // check whether its a dynamic texture
6624                 // 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]
6625                 dyntexture = CL_GetDynTexture( basename );
6626                 item->base = dyntexture; // either NULL or dyntexture handle
6627         }
6628
6629         R_SkinFrame_MarkUsed(item);
6630         return item;
6631 }
6632
6633 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6634         { \
6635                 unsigned long long avgcolor[5], wsum; \
6636                 int pix, comp, w; \
6637                 avgcolor[0] = 0; \
6638                 avgcolor[1] = 0; \
6639                 avgcolor[2] = 0; \
6640                 avgcolor[3] = 0; \
6641                 avgcolor[4] = 0; \
6642                 wsum = 0; \
6643                 for(pix = 0; pix < cnt; ++pix) \
6644                 { \
6645                         w = 0; \
6646                         for(comp = 0; comp < 3; ++comp) \
6647                                 w += getpixel; \
6648                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6649                         { \
6650                                 ++wsum; \
6651                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6652                                 w = getpixel; \
6653                                 for(comp = 0; comp < 3; ++comp) \
6654                                         avgcolor[comp] += getpixel * w; \
6655                                 avgcolor[3] += w; \
6656                         } \
6657                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6658                         avgcolor[4] += getpixel; \
6659                 } \
6660                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6661                         avgcolor[3] = 1; \
6662                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6663                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6664                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6665                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6666         }
6667
6668 extern cvar_t gl_picmip;
6669 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6670 {
6671         int j;
6672         unsigned char *pixels;
6673         unsigned char *bumppixels;
6674         unsigned char *basepixels = NULL;
6675         int basepixels_width = 0;
6676         int basepixels_height = 0;
6677         skinframe_t *skinframe;
6678         rtexture_t *ddsbase = NULL;
6679         qboolean ddshasalpha = false;
6680         float ddsavgcolor[4];
6681         char basename[MAX_QPATH];
6682         int miplevel = R_PicmipForFlags(textureflags);
6683         int savemiplevel = miplevel;
6684         int mymiplevel;
6685
6686         if (cls.state == ca_dedicated)
6687                 return NULL;
6688
6689         // return an existing skinframe if already loaded
6690         // if loading of the first image fails, don't make a new skinframe as it
6691         // would cause all future lookups of this to be missing
6692         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6693         if (skinframe && skinframe->base)
6694                 return skinframe;
6695
6696         Image_StripImageExtension(name, basename, sizeof(basename));
6697
6698         // check for DDS texture file first
6699         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6700         {
6701                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6702                 if (basepixels == NULL)
6703                         return NULL;
6704         }
6705
6706         // FIXME handle miplevel
6707
6708         if (developer_loading.integer)
6709                 Con_Printf("loading skin \"%s\"\n", name);
6710
6711         // we've got some pixels to store, so really allocate this new texture now
6712         if (!skinframe)
6713                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6714         skinframe->stain = NULL;
6715         skinframe->merged = NULL;
6716         skinframe->base = NULL;
6717         skinframe->pants = NULL;
6718         skinframe->shirt = NULL;
6719         skinframe->nmap = NULL;
6720         skinframe->gloss = NULL;
6721         skinframe->glow = NULL;
6722         skinframe->fog = NULL;
6723         skinframe->reflect = NULL;
6724         skinframe->hasalpha = false;
6725
6726         if (ddsbase)
6727         {
6728                 skinframe->base = ddsbase;
6729                 skinframe->hasalpha = ddshasalpha;
6730                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6731                 if (r_loadfog && skinframe->hasalpha)
6732                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6733                 //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]);
6734         }
6735         else
6736         {
6737                 basepixels_width = image_width;
6738                 basepixels_height = image_height;
6739                 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);
6740                 if (textureflags & TEXF_ALPHA)
6741                 {
6742                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6743                         {
6744                                 if (basepixels[j] < 255)
6745                                 {
6746                                         skinframe->hasalpha = true;
6747                                         break;
6748                                 }
6749                         }
6750                         if (r_loadfog && skinframe->hasalpha)
6751                         {
6752                                 // has transparent pixels
6753                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6754                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6755                                 {
6756                                         pixels[j+0] = 255;
6757                                         pixels[j+1] = 255;
6758                                         pixels[j+2] = 255;
6759                                         pixels[j+3] = basepixels[j+3];
6760                                 }
6761                                 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);
6762                                 Mem_Free(pixels);
6763                         }
6764                 }
6765                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6766                 //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]);
6767                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6768                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6769                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6770                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6771         }
6772
6773         if (r_loaddds)
6774         {
6775                 mymiplevel = savemiplevel;
6776                 if (r_loadnormalmap)
6777                         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);
6778                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6779                 if (r_loadgloss)
6780                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6781                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6782                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6783                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6784         }
6785
6786         // _norm is the name used by tenebrae and has been adopted as standard
6787         if (r_loadnormalmap && skinframe->nmap == NULL)
6788         {
6789                 mymiplevel = savemiplevel;
6790                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6791                 {
6792                         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);
6793                         Mem_Free(pixels);
6794                         pixels = NULL;
6795                 }
6796                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6797                 {
6798                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6799                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6800                         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);
6801                         Mem_Free(pixels);
6802                         Mem_Free(bumppixels);
6803                 }
6804                 else if (r_shadow_bumpscale_basetexture.value > 0)
6805                 {
6806                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6807                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6808                         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);
6809                         Mem_Free(pixels);
6810                 }
6811                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6812                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6813         }
6814
6815         // _luma is supported only for tenebrae compatibility
6816         // _glow is the preferred name
6817         mymiplevel = savemiplevel;
6818         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))))
6819         {
6820                 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);
6821                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6822                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6823                 Mem_Free(pixels);pixels = NULL;
6824         }
6825
6826         mymiplevel = savemiplevel;
6827         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6828         {
6829                 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);
6830                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6831                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6832                 Mem_Free(pixels);
6833                 pixels = NULL;
6834         }
6835
6836         mymiplevel = savemiplevel;
6837         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6838         {
6839                 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);
6840                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6841                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6842                 Mem_Free(pixels);
6843                 pixels = NULL;
6844         }
6845
6846         mymiplevel = savemiplevel;
6847         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6848         {
6849                 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);
6850                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6851                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6852                 Mem_Free(pixels);
6853                 pixels = NULL;
6854         }
6855
6856         mymiplevel = savemiplevel;
6857         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6858         {
6859                 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);
6860                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6861                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6862                 Mem_Free(pixels);
6863                 pixels = NULL;
6864         }
6865
6866         if (basepixels)
6867                 Mem_Free(basepixels);
6868
6869         return skinframe;
6870 }
6871
6872 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6873 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6874 {
6875         int i;
6876         unsigned char *temp1, *temp2;
6877         skinframe_t *skinframe;
6878
6879         if (cls.state == ca_dedicated)
6880                 return NULL;
6881
6882         // if already loaded just return it, otherwise make a new skinframe
6883         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6884         if (skinframe && skinframe->base)
6885                 return skinframe;
6886
6887         skinframe->stain = NULL;
6888         skinframe->merged = NULL;
6889         skinframe->base = NULL;
6890         skinframe->pants = NULL;
6891         skinframe->shirt = NULL;
6892         skinframe->nmap = NULL;
6893         skinframe->gloss = NULL;
6894         skinframe->glow = NULL;
6895         skinframe->fog = NULL;
6896         skinframe->reflect = NULL;
6897         skinframe->hasalpha = false;
6898
6899         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6900         if (!skindata)
6901                 return NULL;
6902
6903         if (developer_loading.integer)
6904                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6905
6906         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6907         {
6908                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6909                 temp2 = temp1 + width * height * 4;
6910                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6911                 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);
6912                 Mem_Free(temp1);
6913         }
6914         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6915         if (textureflags & TEXF_ALPHA)
6916         {
6917                 for (i = 3;i < width * height * 4;i += 4)
6918                 {
6919                         if (skindata[i] < 255)
6920                         {
6921                                 skinframe->hasalpha = true;
6922                                 break;
6923                         }
6924                 }
6925                 if (r_loadfog && skinframe->hasalpha)
6926                 {
6927                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6928                         memcpy(fogpixels, skindata, width * height * 4);
6929                         for (i = 0;i < width * height * 4;i += 4)
6930                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6931                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6932                         Mem_Free(fogpixels);
6933                 }
6934         }
6935
6936         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6937         //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]);
6938
6939         return skinframe;
6940 }
6941
6942 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6943 {
6944         int i;
6945         int featuresmask;
6946         skinframe_t *skinframe;
6947
6948         if (cls.state == ca_dedicated)
6949                 return NULL;
6950
6951         // if already loaded just return it, otherwise make a new skinframe
6952         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6953         if (skinframe && skinframe->base)
6954                 return skinframe;
6955
6956         skinframe->stain = NULL;
6957         skinframe->merged = NULL;
6958         skinframe->base = NULL;
6959         skinframe->pants = NULL;
6960         skinframe->shirt = NULL;
6961         skinframe->nmap = NULL;
6962         skinframe->gloss = NULL;
6963         skinframe->glow = NULL;
6964         skinframe->fog = NULL;
6965         skinframe->reflect = NULL;
6966         skinframe->hasalpha = false;
6967
6968         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6969         if (!skindata)
6970                 return NULL;
6971
6972         if (developer_loading.integer)
6973                 Con_Printf("loading quake skin \"%s\"\n", name);
6974
6975         // 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)
6976         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6977         memcpy(skinframe->qpixels, skindata, width*height);
6978         skinframe->qwidth = width;
6979         skinframe->qheight = height;
6980
6981         featuresmask = 0;
6982         for (i = 0;i < width * height;i++)
6983                 featuresmask |= palette_featureflags[skindata[i]];
6984
6985         skinframe->hasalpha = false;
6986         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6987         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6988         skinframe->qgeneratemerged = true;
6989         skinframe->qgeneratebase = skinframe->qhascolormapping;
6990         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6991
6992         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6993         //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]);
6994
6995         return skinframe;
6996 }
6997
6998 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6999 {
7000         int width;
7001         int height;
7002         unsigned char *skindata;
7003
7004         if (!skinframe->qpixels)
7005                 return;
7006
7007         if (!skinframe->qhascolormapping)
7008                 colormapped = false;
7009
7010         if (colormapped)
7011         {
7012                 if (!skinframe->qgeneratebase)
7013                         return;
7014         }
7015         else
7016         {
7017                 if (!skinframe->qgeneratemerged)
7018                         return;
7019         }
7020
7021         width = skinframe->qwidth;
7022         height = skinframe->qheight;
7023         skindata = skinframe->qpixels;
7024
7025         if (skinframe->qgeneratenmap)
7026         {
7027                 unsigned char *temp1, *temp2;
7028                 skinframe->qgeneratenmap = false;
7029                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
7030                 temp2 = temp1 + width * height * 4;
7031                 // use either a custom palette or the quake palette
7032                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
7033                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
7034                 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);
7035                 Mem_Free(temp1);
7036         }
7037
7038         if (skinframe->qgenerateglow)
7039         {
7040                 skinframe->qgenerateglow = false;
7041                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
7042         }
7043
7044         if (colormapped)
7045         {
7046                 skinframe->qgeneratebase = false;
7047                 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);
7048                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
7049                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
7050         }
7051         else
7052         {
7053                 skinframe->qgeneratemerged = false;
7054                 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);
7055         }
7056
7057         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
7058         {
7059                 Mem_Free(skinframe->qpixels);
7060                 skinframe->qpixels = NULL;
7061         }
7062 }
7063
7064 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)
7065 {
7066         int i;
7067         skinframe_t *skinframe;
7068
7069         if (cls.state == ca_dedicated)
7070                 return NULL;
7071
7072         // if already loaded just return it, otherwise make a new skinframe
7073         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
7074         if (skinframe && skinframe->base)
7075                 return skinframe;
7076
7077         skinframe->stain = NULL;
7078         skinframe->merged = NULL;
7079         skinframe->base = NULL;
7080         skinframe->pants = NULL;
7081         skinframe->shirt = NULL;
7082         skinframe->nmap = NULL;
7083         skinframe->gloss = NULL;
7084         skinframe->glow = NULL;
7085         skinframe->fog = NULL;
7086         skinframe->reflect = NULL;
7087         skinframe->hasalpha = false;
7088
7089         // if no data was provided, then clearly the caller wanted to get a blank skinframe
7090         if (!skindata)
7091                 return NULL;
7092
7093         if (developer_loading.integer)
7094                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
7095
7096         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
7097         if (textureflags & TEXF_ALPHA)
7098         {
7099                 for (i = 0;i < width * height;i++)
7100                 {
7101                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
7102                         {
7103                                 skinframe->hasalpha = true;
7104                                 break;
7105                         }
7106                 }
7107                 if (r_loadfog && skinframe->hasalpha)
7108                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
7109         }
7110
7111         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
7112         //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]);
7113
7114         return skinframe;
7115 }
7116
7117 skinframe_t *R_SkinFrame_LoadMissing(void)
7118 {
7119         skinframe_t *skinframe;
7120
7121         if (cls.state == ca_dedicated)
7122                 return NULL;
7123
7124         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
7125         skinframe->stain = NULL;
7126         skinframe->merged = NULL;
7127         skinframe->base = NULL;
7128         skinframe->pants = NULL;
7129         skinframe->shirt = NULL;
7130         skinframe->nmap = NULL;
7131         skinframe->gloss = NULL;
7132         skinframe->glow = NULL;
7133         skinframe->fog = NULL;
7134         skinframe->reflect = NULL;
7135         skinframe->hasalpha = false;
7136
7137         skinframe->avgcolor[0] = rand() / RAND_MAX;
7138         skinframe->avgcolor[1] = rand() / RAND_MAX;
7139         skinframe->avgcolor[2] = rand() / RAND_MAX;
7140         skinframe->avgcolor[3] = 1;
7141
7142         return skinframe;
7143 }
7144
7145 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
7146 typedef struct suffixinfo_s
7147 {
7148         const char *suffix;
7149         qboolean flipx, flipy, flipdiagonal;
7150 }
7151 suffixinfo_t;
7152 static suffixinfo_t suffix[3][6] =
7153 {
7154         {
7155                 {"px",   false, false, false},
7156                 {"nx",   false, false, false},
7157                 {"py",   false, false, false},
7158                 {"ny",   false, false, false},
7159                 {"pz",   false, false, false},
7160                 {"nz",   false, false, false}
7161         },
7162         {
7163                 {"posx", false, false, false},
7164                 {"negx", false, false, false},
7165                 {"posy", false, false, false},
7166                 {"negy", false, false, false},
7167                 {"posz", false, false, false},
7168                 {"negz", false, false, false}
7169         },
7170         {
7171                 {"rt",    true, false,  true},
7172                 {"lf",   false,  true,  true},
7173                 {"ft",    true,  true, false},
7174                 {"bk",   false, false, false},
7175                 {"up",    true, false,  true},
7176                 {"dn",    true, false,  true}
7177         }
7178 };
7179
7180 static int componentorder[4] = {0, 1, 2, 3};
7181
7182 rtexture_t *R_LoadCubemap(const char *basename)
7183 {
7184         int i, j, cubemapsize;
7185         unsigned char *cubemappixels, *image_buffer;
7186         rtexture_t *cubemaptexture;
7187         char name[256];
7188         // must start 0 so the first loadimagepixels has no requested width/height
7189         cubemapsize = 0;
7190         cubemappixels = NULL;
7191         cubemaptexture = NULL;
7192         // keep trying different suffix groups (posx, px, rt) until one loads
7193         for (j = 0;j < 3 && !cubemappixels;j++)
7194         {
7195                 // load the 6 images in the suffix group
7196                 for (i = 0;i < 6;i++)
7197                 {
7198                         // generate an image name based on the base and and suffix
7199                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
7200                         // load it
7201                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
7202                         {
7203                                 // an image loaded, make sure width and height are equal
7204                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
7205                                 {
7206                                         // if this is the first image to load successfully, allocate the cubemap memory
7207                                         if (!cubemappixels && image_width >= 1)
7208                                         {
7209                                                 cubemapsize = image_width;
7210                                                 // note this clears to black, so unavailable sides are black
7211                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7212                                         }
7213                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7214                                         if (cubemappixels)
7215                                                 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);
7216                                 }
7217                                 else
7218                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7219                                 // free the image
7220                                 Mem_Free(image_buffer);
7221                         }
7222                 }
7223         }
7224         // if a cubemap loaded, upload it
7225         if (cubemappixels)
7226         {
7227                 if (developer_loading.integer)
7228                         Con_Printf("loading cubemap \"%s\"\n", basename);
7229
7230                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7231                 Mem_Free(cubemappixels);
7232         }
7233         else
7234         {
7235                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7236                 if (developer_loading.integer)
7237                 {
7238                         Con_Printf("(tried tried images ");
7239                         for (j = 0;j < 3;j++)
7240                                 for (i = 0;i < 6;i++)
7241                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7242                         Con_Print(" and was unable to find any of them).\n");
7243                 }
7244         }
7245         return cubemaptexture;
7246 }
7247
7248 rtexture_t *R_GetCubemap(const char *basename)
7249 {
7250         int i;
7251         for (i = 0;i < r_texture_numcubemaps;i++)
7252                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7253                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7254         if (i >= MAX_CUBEMAPS)
7255                 return r_texture_whitecube;
7256         r_texture_numcubemaps++;
7257         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7258         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7259         return r_texture_cubemaps[i].texture;
7260 }
7261
7262 void R_FreeCubemaps(void)
7263 {
7264         int i;
7265         for (i = 0;i < r_texture_numcubemaps;i++)
7266         {
7267                 if (developer_loading.integer)
7268                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7269                 if (r_texture_cubemaps[i].texture)
7270                         R_FreeTexture(r_texture_cubemaps[i].texture);
7271         }
7272         r_texture_numcubemaps = 0;
7273 }
7274
7275 void R_Main_FreeViewCache(void)
7276 {
7277         if (r_refdef.viewcache.entityvisible)
7278                 Mem_Free(r_refdef.viewcache.entityvisible);
7279         if (r_refdef.viewcache.world_pvsbits)
7280                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7281         if (r_refdef.viewcache.world_leafvisible)
7282                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7283         if (r_refdef.viewcache.world_surfacevisible)
7284                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7285         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7286 }
7287
7288 void R_Main_ResizeViewCache(void)
7289 {
7290         int numentities = r_refdef.scene.numentities;
7291         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7292         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7293         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7294         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7295         if (r_refdef.viewcache.maxentities < numentities)
7296         {
7297                 r_refdef.viewcache.maxentities = numentities;
7298                 if (r_refdef.viewcache.entityvisible)
7299                         Mem_Free(r_refdef.viewcache.entityvisible);
7300                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7301         }
7302         if (r_refdef.viewcache.world_numclusters != numclusters)
7303         {
7304                 r_refdef.viewcache.world_numclusters = numclusters;
7305                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7306                 if (r_refdef.viewcache.world_pvsbits)
7307                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7308                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7309         }
7310         if (r_refdef.viewcache.world_numleafs != numleafs)
7311         {
7312                 r_refdef.viewcache.world_numleafs = numleafs;
7313                 if (r_refdef.viewcache.world_leafvisible)
7314                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7315                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7316         }
7317         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7318         {
7319                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7320                 if (r_refdef.viewcache.world_surfacevisible)
7321                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7322                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7323         }
7324 }
7325
7326 extern rtexture_t *loadingscreentexture;
7327 void gl_main_start(void)
7328 {
7329         loadingscreentexture = NULL;
7330         r_texture_blanknormalmap = NULL;
7331         r_texture_white = NULL;
7332         r_texture_grey128 = NULL;
7333         r_texture_black = NULL;
7334         r_texture_whitecube = NULL;
7335         r_texture_normalizationcube = NULL;
7336         r_texture_fogattenuation = NULL;
7337         r_texture_fogheighttexture = NULL;
7338         r_texture_gammaramps = NULL;
7339         r_texture_numcubemaps = 0;
7340
7341         r_loaddds = r_texture_dds_load.integer != 0;
7342         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7343
7344         switch(vid.renderpath)
7345         {
7346         case RENDERPATH_GL20:
7347         case RENDERPATH_CGGL:
7348         case RENDERPATH_D3D9:
7349         case RENDERPATH_D3D10:
7350         case RENDERPATH_D3D11:
7351         case RENDERPATH_SOFT:
7352                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7353                 Cvar_SetValueQuick(&gl_combine, 1);
7354                 Cvar_SetValueQuick(&r_glsl, 1);
7355                 r_loadnormalmap = true;
7356                 r_loadgloss = true;
7357                 r_loadfog = false;
7358                 break;
7359         case RENDERPATH_GL13:
7360                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7361                 Cvar_SetValueQuick(&gl_combine, 1);
7362                 Cvar_SetValueQuick(&r_glsl, 0);
7363                 r_loadnormalmap = false;
7364                 r_loadgloss = false;
7365                 r_loadfog = true;
7366                 break;
7367         case RENDERPATH_GL11:
7368                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7369                 Cvar_SetValueQuick(&gl_combine, 0);
7370                 Cvar_SetValueQuick(&r_glsl, 0);
7371                 r_loadnormalmap = false;
7372                 r_loadgloss = false;
7373                 r_loadfog = true;
7374                 break;
7375         case RENDERPATH_GLES2:
7376                 Cvar_SetValueQuick(&r_textureunits, 1);
7377                 Cvar_SetValueQuick(&gl_combine, 1);
7378                 Cvar_SetValueQuick(&r_glsl, 1);
7379                 r_loadnormalmap = true;
7380                 r_loadgloss = false;
7381                 r_loadfog = false;
7382                 break;
7383         }
7384
7385         R_AnimCache_Free();
7386         R_FrameData_Reset();
7387
7388         r_numqueries = 0;
7389         r_maxqueries = 0;
7390         memset(r_queries, 0, sizeof(r_queries));
7391
7392         r_qwskincache = NULL;
7393         r_qwskincache_size = 0;
7394
7395         // set up r_skinframe loading system for textures
7396         memset(&r_skinframe, 0, sizeof(r_skinframe));
7397         r_skinframe.loadsequence = 1;
7398         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7399
7400         r_main_texturepool = R_AllocTexturePool();
7401         R_BuildBlankTextures();
7402         R_BuildNoTexture();
7403         if (vid.support.arb_texture_cube_map)
7404         {
7405                 R_BuildWhiteCube();
7406                 R_BuildNormalizationCube();
7407         }
7408         r_texture_fogattenuation = NULL;
7409         r_texture_fogheighttexture = NULL;
7410         r_texture_gammaramps = NULL;
7411         //r_texture_fogintensity = NULL;
7412         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7413         memset(&r_waterstate, 0, sizeof(r_waterstate));
7414         r_glsl_permutation = NULL;
7415         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7416         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7417         glslshaderstring = NULL;
7418 #ifdef SUPPORTCG
7419         r_cg_permutation = NULL;
7420         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7421         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7422         cgshaderstring = NULL;
7423 #endif
7424 #ifdef SUPPORTD3D
7425         r_hlsl_permutation = NULL;
7426         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7427         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7428         hlslshaderstring = NULL;
7429 #endif
7430         memset(&r_svbsp, 0, sizeof (r_svbsp));
7431
7432         r_refdef.fogmasktable_density = 0;
7433 }
7434
7435 void gl_main_shutdown(void)
7436 {
7437         R_AnimCache_Free();
7438         R_FrameData_Reset();
7439
7440         R_Main_FreeViewCache();
7441
7442         switch(vid.renderpath)
7443         {
7444         case RENDERPATH_GL11:
7445         case RENDERPATH_GL13:
7446         case RENDERPATH_GL20:
7447         case RENDERPATH_CGGL:
7448         case RENDERPATH_GLES2:
7449                 if (r_maxqueries)
7450                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7451                 break;
7452         case RENDERPATH_D3D9:
7453                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7454                 break;
7455         case RENDERPATH_D3D10:
7456                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7457                 break;
7458         case RENDERPATH_D3D11:
7459                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7460                 break;
7461         case RENDERPATH_SOFT:
7462                 break;
7463         }
7464
7465         r_numqueries = 0;
7466         r_maxqueries = 0;
7467         memset(r_queries, 0, sizeof(r_queries));
7468
7469         r_qwskincache = NULL;
7470         r_qwskincache_size = 0;
7471
7472         // clear out the r_skinframe state
7473         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7474         memset(&r_skinframe, 0, sizeof(r_skinframe));
7475
7476         if (r_svbsp.nodes)
7477                 Mem_Free(r_svbsp.nodes);
7478         memset(&r_svbsp, 0, sizeof (r_svbsp));
7479         R_FreeTexturePool(&r_main_texturepool);
7480         loadingscreentexture = NULL;
7481         r_texture_blanknormalmap = NULL;
7482         r_texture_white = NULL;
7483         r_texture_grey128 = NULL;
7484         r_texture_black = NULL;
7485         r_texture_whitecube = NULL;
7486         r_texture_normalizationcube = NULL;
7487         r_texture_fogattenuation = NULL;
7488         r_texture_fogheighttexture = NULL;
7489         r_texture_gammaramps = NULL;
7490         r_texture_numcubemaps = 0;
7491         //r_texture_fogintensity = NULL;
7492         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7493         memset(&r_waterstate, 0, sizeof(r_waterstate));
7494         R_GLSL_Restart_f();
7495
7496         r_glsl_permutation = NULL;
7497         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7498         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
7499         glslshaderstring = NULL;
7500 #ifdef SUPPORTCG
7501         r_cg_permutation = NULL;
7502         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7503         Mem_ExpandableArray_FreeArray(&r_cg_permutationarray);
7504         cgshaderstring = NULL;
7505 #endif
7506 #ifdef SUPPORTD3D
7507         r_hlsl_permutation = NULL;
7508         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7509         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
7510         hlslshaderstring = NULL;
7511 #endif
7512 }
7513
7514 extern void CL_ParseEntityLump(char *entitystring);
7515 void gl_main_newmap(void)
7516 {
7517         // FIXME: move this code to client
7518         char *entities, entname[MAX_QPATH];
7519         if (r_qwskincache)
7520                 Mem_Free(r_qwskincache);
7521         r_qwskincache = NULL;
7522         r_qwskincache_size = 0;
7523         if (cl.worldmodel)
7524         {
7525                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7526                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7527                 {
7528                         CL_ParseEntityLump(entities);
7529                         Mem_Free(entities);
7530                         return;
7531                 }
7532                 if (cl.worldmodel->brush.entities)
7533                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7534         }
7535         R_Main_FreeViewCache();
7536
7537         R_FrameData_Reset();
7538 }
7539
7540 void GL_Main_Init(void)
7541 {
7542         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7543
7544         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7545         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7546         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7547         if (gamemode == GAME_NEHAHRA)
7548         {
7549                 Cvar_RegisterVariable (&gl_fogenable);
7550                 Cvar_RegisterVariable (&gl_fogdensity);
7551                 Cvar_RegisterVariable (&gl_fogred);
7552                 Cvar_RegisterVariable (&gl_foggreen);
7553                 Cvar_RegisterVariable (&gl_fogblue);
7554                 Cvar_RegisterVariable (&gl_fogstart);
7555                 Cvar_RegisterVariable (&gl_fogend);
7556                 Cvar_RegisterVariable (&gl_skyclip);
7557         }
7558         Cvar_RegisterVariable(&r_motionblur);
7559         Cvar_RegisterVariable(&r_motionblur_maxblur);
7560         Cvar_RegisterVariable(&r_motionblur_bmin);
7561         Cvar_RegisterVariable(&r_motionblur_vmin);
7562         Cvar_RegisterVariable(&r_motionblur_vmax);
7563         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7564         Cvar_RegisterVariable(&r_motionblur_randomize);
7565         Cvar_RegisterVariable(&r_damageblur);
7566         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7567         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7568         Cvar_RegisterVariable(&r_equalize_entities_by);
7569         Cvar_RegisterVariable(&r_equalize_entities_to);
7570         Cvar_RegisterVariable(&r_depthfirst);
7571         Cvar_RegisterVariable(&r_useinfinitefarclip);
7572         Cvar_RegisterVariable(&r_farclip_base);
7573         Cvar_RegisterVariable(&r_farclip_world);
7574         Cvar_RegisterVariable(&r_nearclip);
7575         Cvar_RegisterVariable(&r_showbboxes);
7576         Cvar_RegisterVariable(&r_showsurfaces);
7577         Cvar_RegisterVariable(&r_showtris);
7578         Cvar_RegisterVariable(&r_shownormals);
7579         Cvar_RegisterVariable(&r_showlighting);
7580         Cvar_RegisterVariable(&r_showshadowvolumes);
7581         Cvar_RegisterVariable(&r_showcollisionbrushes);
7582         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7583         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7584         Cvar_RegisterVariable(&r_showdisabledepthtest);
7585         Cvar_RegisterVariable(&r_drawportals);
7586         Cvar_RegisterVariable(&r_drawentities);
7587         Cvar_RegisterVariable(&r_draw2d);
7588         Cvar_RegisterVariable(&r_drawworld);
7589         Cvar_RegisterVariable(&r_cullentities_trace);
7590         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7591         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7592         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7593         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7594         Cvar_RegisterVariable(&r_drawviewmodel);
7595         Cvar_RegisterVariable(&r_drawexteriormodel);
7596         Cvar_RegisterVariable(&r_speeds);
7597         Cvar_RegisterVariable(&r_fullbrights);
7598         Cvar_RegisterVariable(&r_wateralpha);
7599         Cvar_RegisterVariable(&r_dynamic);
7600         Cvar_RegisterVariable(&r_fakelight);
7601         Cvar_RegisterVariable(&r_fakelight_intensity);
7602         Cvar_RegisterVariable(&r_fullbright);
7603         Cvar_RegisterVariable(&r_shadows);
7604         Cvar_RegisterVariable(&r_shadows_darken);
7605         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7606         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7607         Cvar_RegisterVariable(&r_shadows_throwdistance);
7608         Cvar_RegisterVariable(&r_shadows_throwdirection);
7609         Cvar_RegisterVariable(&r_shadows_focus);
7610         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7611         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7612         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7613         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7614         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7615         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7616         Cvar_RegisterVariable(&r_fog_exp2);
7617         Cvar_RegisterVariable(&r_drawfog);
7618         Cvar_RegisterVariable(&r_transparentdepthmasking);
7619         Cvar_RegisterVariable(&r_texture_dds_load);
7620         Cvar_RegisterVariable(&r_texture_dds_save);
7621         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7622         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7623         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7624         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7625         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7626         Cvar_RegisterVariable(&r_textureunits);
7627         Cvar_RegisterVariable(&gl_combine);
7628         Cvar_RegisterVariable(&r_glsl);
7629         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7630         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7631         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7632         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7633         Cvar_RegisterVariable(&r_glsl_postprocess);
7634         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7635         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7636         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7637         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7638         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
7639         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
7640         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
7641         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
7642
7643         Cvar_RegisterVariable(&r_water);
7644         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7645         Cvar_RegisterVariable(&r_water_clippingplanebias);
7646         Cvar_RegisterVariable(&r_water_refractdistort);
7647         Cvar_RegisterVariable(&r_water_reflectdistort);
7648         Cvar_RegisterVariable(&r_water_scissormode);
7649         Cvar_RegisterVariable(&r_lerpsprites);
7650         Cvar_RegisterVariable(&r_lerpmodels);
7651         Cvar_RegisterVariable(&r_lerplightstyles);
7652         Cvar_RegisterVariable(&r_waterscroll);
7653         Cvar_RegisterVariable(&r_bloom);
7654         Cvar_RegisterVariable(&r_bloom_colorscale);
7655         Cvar_RegisterVariable(&r_bloom_brighten);
7656         Cvar_RegisterVariable(&r_bloom_blur);
7657         Cvar_RegisterVariable(&r_bloom_resolution);
7658         Cvar_RegisterVariable(&r_bloom_colorexponent);
7659         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7660         Cvar_RegisterVariable(&r_hdr);
7661         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7662         Cvar_RegisterVariable(&r_hdr_glowintensity);
7663         Cvar_RegisterVariable(&r_hdr_range);
7664         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7665         Cvar_RegisterVariable(&developer_texturelogging);
7666         Cvar_RegisterVariable(&gl_lightmaps);
7667         Cvar_RegisterVariable(&r_test);
7668         Cvar_RegisterVariable(&r_glsl_saturation);
7669         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7670         Cvar_RegisterVariable(&r_framedatasize);
7671         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7672                 Cvar_SetValue("r_fullbrights", 0);
7673         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7674
7675         Cvar_RegisterVariable(&r_track_sprites);
7676         Cvar_RegisterVariable(&r_track_sprites_flags);
7677         Cvar_RegisterVariable(&r_track_sprites_scalew);
7678         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7679         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7680         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7681         Cvar_RegisterVariable(&r_overheadsprites_scalex);
7682         Cvar_RegisterVariable(&r_overheadsprites_scaley);
7683 }
7684
7685 extern void R_Textures_Init(void);
7686 extern void GL_Draw_Init(void);
7687 extern void GL_Main_Init(void);
7688 extern void R_Shadow_Init(void);
7689 extern void R_Sky_Init(void);
7690 extern void GL_Surf_Init(void);
7691 extern void R_Particles_Init(void);
7692 extern void R_Explosion_Init(void);
7693 extern void gl_backend_init(void);
7694 extern void Sbar_Init(void);
7695 extern void R_LightningBeams_Init(void);
7696 extern void Mod_RenderInit(void);
7697 extern void Font_Init(void);
7698
7699 void Render_Init(void)
7700 {
7701         gl_backend_init();
7702         R_Textures_Init();
7703         GL_Main_Init();
7704         Font_Init();
7705         GL_Draw_Init();
7706         R_Shadow_Init();
7707         R_Sky_Init();
7708         GL_Surf_Init();
7709         Sbar_Init();
7710         R_Particles_Init();
7711         R_Explosion_Init();
7712         R_LightningBeams_Init();
7713         Mod_RenderInit();
7714 }
7715
7716 /*
7717 ===============
7718 GL_Init
7719 ===============
7720 */
7721 extern char *ENGINE_EXTENSIONS;
7722 void GL_Init (void)
7723 {
7724         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7725         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7726         gl_version = (const char *)qglGetString(GL_VERSION);
7727         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7728
7729         if (!gl_extensions)
7730                 gl_extensions = "";
7731         if (!gl_platformextensions)
7732                 gl_platformextensions = "";
7733
7734         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7735         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7736         Con_Printf("GL_VERSION: %s\n", gl_version);
7737         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7738         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7739
7740         VID_CheckExtensions();
7741
7742         // LordHavoc: report supported extensions
7743         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7744
7745         // clear to black (loading plaque will be seen over this)
7746         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7747 }
7748
7749 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7750 {
7751         int i;
7752         mplane_t *p;
7753         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7754         {
7755                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7756                 if (i == 4)
7757                         continue;
7758                 p = r_refdef.view.frustum + i;
7759                 switch(p->signbits)
7760                 {
7761                 default:
7762                 case 0:
7763                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7764                                 return true;
7765                         break;
7766                 case 1:
7767                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7768                                 return true;
7769                         break;
7770                 case 2:
7771                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7772                                 return true;
7773                         break;
7774                 case 3:
7775                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7776                                 return true;
7777                         break;
7778                 case 4:
7779                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7780                                 return true;
7781                         break;
7782                 case 5:
7783                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7784                                 return true;
7785                         break;
7786                 case 6:
7787                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7788                                 return true;
7789                         break;
7790                 case 7:
7791                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7792                                 return true;
7793                         break;
7794                 }
7795         }
7796         return false;
7797 }
7798
7799 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7800 {
7801         int i;
7802         const mplane_t *p;
7803         for (i = 0;i < numplanes;i++)
7804         {
7805                 p = planes + i;
7806                 switch(p->signbits)
7807                 {
7808                 default:
7809                 case 0:
7810                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7811                                 return true;
7812                         break;
7813                 case 1:
7814                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7815                                 return true;
7816                         break;
7817                 case 2:
7818                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7819                                 return true;
7820                         break;
7821                 case 3:
7822                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7823                                 return true;
7824                         break;
7825                 case 4:
7826                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7827                                 return true;
7828                         break;
7829                 case 5:
7830                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7831                                 return true;
7832                         break;
7833                 case 6:
7834                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7835                                 return true;
7836                         break;
7837                 case 7:
7838                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7839                                 return true;
7840                         break;
7841                 }
7842         }
7843         return false;
7844 }
7845
7846 //==================================================================================
7847
7848 // LordHavoc: this stores temporary data used within the same frame
7849
7850 typedef struct r_framedata_mem_s
7851 {
7852         struct r_framedata_mem_s *purge; // older mem block to free on next frame
7853         size_t size; // how much usable space
7854         size_t current; // how much space in use
7855         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7856         size_t wantedsize; // how much space was allocated
7857         unsigned char *data; // start of real data (16byte aligned)
7858 }
7859 r_framedata_mem_t;
7860
7861 static r_framedata_mem_t *r_framedata_mem;
7862
7863 void R_FrameData_Reset(void)
7864 {
7865         while (r_framedata_mem)
7866         {
7867                 r_framedata_mem_t *next = r_framedata_mem->purge;
7868                 Mem_Free(r_framedata_mem);
7869                 r_framedata_mem = next;
7870         }
7871 }
7872
7873 void R_FrameData_Resize(void)
7874 {
7875         size_t wantedsize;
7876         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7877         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7878         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7879         {
7880                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
7881                 newmem->wantedsize = wantedsize;
7882                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7883                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7884                 newmem->current = 0;
7885                 newmem->mark = 0;
7886                 newmem->purge = r_framedata_mem;
7887                 r_framedata_mem = newmem;
7888         }
7889 }
7890
7891 void R_FrameData_NewFrame(void)
7892 {
7893         R_FrameData_Resize();
7894         if (!r_framedata_mem)
7895                 return;
7896         // if we ran out of space on the last frame, free the old memory now
7897         while (r_framedata_mem->purge)
7898         {
7899                 // repeatedly remove the second item in the list, leaving only head
7900                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7901                 Mem_Free(r_framedata_mem->purge);
7902                 r_framedata_mem->purge = next;
7903         }
7904         // reset the current mem pointer
7905         r_framedata_mem->current = 0;
7906         r_framedata_mem->mark = 0;
7907 }
7908
7909 void *R_FrameData_Alloc(size_t size)
7910 {
7911         void *data;
7912
7913         // align to 16 byte boundary - the data pointer is already aligned, so we
7914         // only need to ensure the size of every allocation is also aligned
7915         size = (size + 15) & ~15;
7916
7917         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
7918         {
7919                 // emergency - we ran out of space, allocate more memory
7920                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
7921                 R_FrameData_Resize();
7922         }
7923
7924         data = r_framedata_mem->data + r_framedata_mem->current;
7925         r_framedata_mem->current += size;
7926
7927         // count the usage for stats
7928         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
7929         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
7930
7931         return (void *)data;
7932 }
7933
7934 void *R_FrameData_Store(size_t size, void *data)
7935 {
7936         void *d = R_FrameData_Alloc(size);
7937         if (d && data)
7938                 memcpy(d, data, size);
7939         return d;
7940 }
7941
7942 void R_FrameData_SetMark(void)
7943 {
7944         if (!r_framedata_mem)
7945                 return;
7946         r_framedata_mem->mark = r_framedata_mem->current;
7947 }
7948
7949 void R_FrameData_ReturnToMark(void)
7950 {
7951         if (!r_framedata_mem)
7952                 return;
7953         r_framedata_mem->current = r_framedata_mem->mark;
7954 }
7955
7956 //==================================================================================
7957
7958 // LordHavoc: animcache originally written by Echon, rewritten since then
7959
7960 /**
7961  * Animation cache prevents re-generating mesh data for an animated model
7962  * multiple times in one frame for lighting, shadowing, reflections, etc.
7963  */
7964
7965 void R_AnimCache_Free(void)
7966 {
7967 }
7968
7969 void R_AnimCache_ClearCache(void)
7970 {
7971         int i;
7972         entity_render_t *ent;
7973
7974         for (i = 0;i < r_refdef.scene.numentities;i++)
7975         {
7976                 ent = r_refdef.scene.entities[i];
7977                 ent->animcache_vertex3f = NULL;
7978                 ent->animcache_normal3f = NULL;
7979                 ent->animcache_svector3f = NULL;
7980                 ent->animcache_tvector3f = NULL;
7981                 ent->animcache_vertexmesh = NULL;
7982                 ent->animcache_vertex3fbuffer = NULL;
7983                 ent->animcache_vertexmeshbuffer = NULL;
7984         }
7985 }
7986
7987 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7988 {
7989         int i;
7990
7991         // check if we need the meshbuffers
7992         if (!vid.useinterleavedarrays)
7993                 return;
7994
7995         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7996                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7997         // TODO: upload vertex3f buffer?
7998         if (ent->animcache_vertexmesh)
7999         {
8000                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
8001                 for (i = 0;i < numvertices;i++)
8002                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
8003                 if (ent->animcache_svector3f)
8004                         for (i = 0;i < numvertices;i++)
8005                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
8006                 if (ent->animcache_tvector3f)
8007                         for (i = 0;i < numvertices;i++)
8008                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
8009                 if (ent->animcache_normal3f)
8010                         for (i = 0;i < numvertices;i++)
8011                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
8012                 // TODO: upload vertexmeshbuffer?
8013         }
8014 }
8015
8016 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
8017 {
8018         dp_model_t *model = ent->model;
8019         int numvertices;
8020         // see if it's already cached this frame
8021         if (ent->animcache_vertex3f)
8022         {
8023                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
8024                 if (wantnormals || wanttangents)
8025                 {
8026                         if (ent->animcache_normal3f)
8027                                 wantnormals = false;
8028                         if (ent->animcache_svector3f)
8029                                 wanttangents = false;
8030                         if (wantnormals || wanttangents)
8031                         {
8032                                 numvertices = model->surfmesh.num_vertices;
8033                                 if (wantnormals)
8034                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
8035                                 if (wanttangents)
8036                                 {
8037                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
8038                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
8039                                 }
8040                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
8041                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
8042                         }
8043                 }
8044         }
8045         else
8046         {
8047                 // see if this ent is worth caching
8048                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
8049                         return false;
8050                 // get some memory for this entity and generate mesh data
8051                 numvertices = model->surfmesh.num_vertices;
8052                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
8053                 if (wantnormals)
8054                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
8055                 if (wanttangents)
8056                 {
8057                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
8058                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
8059                 }
8060                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
8061                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
8062         }
8063         return true;
8064 }
8065
8066 void R_AnimCache_CacheVisibleEntities(void)
8067 {
8068         int i;
8069         qboolean wantnormals = true;
8070         qboolean wanttangents = !r_showsurfaces.integer;
8071
8072         switch(vid.renderpath)
8073         {
8074         case RENDERPATH_GL20:
8075         case RENDERPATH_CGGL:
8076         case RENDERPATH_D3D9:
8077         case RENDERPATH_D3D10:
8078         case RENDERPATH_D3D11:
8079         case RENDERPATH_GLES2:
8080                 break;
8081         case RENDERPATH_GL13:
8082         case RENDERPATH_GL11:
8083                 wanttangents = false;
8084                 break;
8085         case RENDERPATH_SOFT:
8086                 break;
8087         }
8088
8089         if (r_shownormals.integer)
8090                 wanttangents = wantnormals = true;
8091
8092         // TODO: thread this
8093         // NOTE: R_PrepareRTLights() also caches entities
8094
8095         for (i = 0;i < r_refdef.scene.numentities;i++)
8096                 if (r_refdef.viewcache.entityvisible[i])
8097                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
8098 }
8099
8100 //==================================================================================
8101
8102 static void R_View_UpdateEntityLighting (void)
8103 {
8104         int i;
8105         entity_render_t *ent;
8106         vec3_t tempdiffusenormal, avg;
8107         vec_t f, fa, fd, fdd;
8108         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
8109
8110         for (i = 0;i < r_refdef.scene.numentities;i++)
8111         {
8112                 ent = r_refdef.scene.entities[i];
8113
8114                 // skip unseen models
8115                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
8116                         continue;
8117
8118                 // skip bsp models
8119                 if (ent->model && ent->model->brush.num_leafs)
8120                 {
8121                         // TODO: use modellight for r_ambient settings on world?
8122                         VectorSet(ent->modellight_ambient, 0, 0, 0);
8123                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
8124                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
8125                         continue;
8126                 }
8127
8128                 // fetch the lighting from the worldmodel data
8129                 VectorClear(ent->modellight_ambient);
8130                 VectorClear(ent->modellight_diffuse);
8131                 VectorClear(tempdiffusenormal);
8132                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
8133                 {
8134                         vec3_t org;
8135                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8136
8137                         // complete lightning for lit sprites
8138                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
8139                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
8140                         {
8141                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
8142                                         org[2] = org[2] + r_overheadsprites_pushback.value;
8143                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
8144                         }
8145                         else
8146                                 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
8147
8148                         if(ent->flags & RENDER_EQUALIZE)
8149                         {
8150                                 // first fix up ambient lighting...
8151                                 if(r_equalize_entities_minambient.value > 0)
8152                                 {
8153                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
8154                                         if(fd > 0)
8155                                         {
8156                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
8157                                                 if(fa < r_equalize_entities_minambient.value * fd)
8158                                                 {
8159                                                         // solve:
8160                                                         //   fa'/fd' = minambient
8161                                                         //   fa'+0.25*fd' = fa+0.25*fd
8162                                                         //   ...
8163                                                         //   fa' = fd' * minambient
8164                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
8165                                                         //   ...
8166                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
8167                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
8168                                                         //   ...
8169                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
8170                                                         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
8171                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
8172                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
8173                                                 }
8174                                         }
8175                                 }
8176
8177                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
8178                                 {
8179                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
8180                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
8181                                         f = fa + 0.25 * fd;
8182                                         if(f > 0)
8183                                         {
8184                                                 // adjust brightness and saturation to target
8185                                                 avg[0] = avg[1] = avg[2] = fa / f;
8186                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
8187                                                 avg[0] = avg[1] = avg[2] = fd / f;
8188                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
8189                                         }
8190                                 }
8191                         }
8192                 }
8193                 else // highly rare
8194                         VectorSet(ent->modellight_ambient, 1, 1, 1);
8195
8196                 // move the light direction into modelspace coordinates for lighting code
8197                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
8198                 if(VectorLength2(ent->modellight_lightdir) == 0)
8199                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
8200                 VectorNormalize(ent->modellight_lightdir);
8201         }
8202 }
8203
8204 #define MAX_LINEOFSIGHTTRACES 64
8205
8206 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
8207 {
8208         int i;
8209         vec3_t boxmins, boxmaxs;
8210         vec3_t start;
8211         vec3_t end;
8212         dp_model_t *model = r_refdef.scene.worldmodel;
8213
8214         if (!model || !model->brush.TraceLineOfSight)
8215                 return true;
8216
8217         // expand the box a little
8218         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
8219         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
8220         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
8221         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
8222         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
8223         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
8224
8225         // return true if eye is inside enlarged box
8226         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
8227                 return true;
8228
8229         // try center
8230         VectorCopy(eye, start);
8231         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
8232         if (model->brush.TraceLineOfSight(model, start, end))
8233                 return true;
8234
8235         // try various random positions
8236         for (i = 0;i < numsamples;i++)
8237         {
8238                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
8239                 if (model->brush.TraceLineOfSight(model, start, end))
8240                         return true;
8241         }
8242
8243         return false;
8244 }
8245
8246
8247 static void R_View_UpdateEntityVisible (void)
8248 {
8249         int i;
8250         int renderimask;
8251         int samples;
8252         entity_render_t *ent;
8253
8254         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8255                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8256                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
8257                 :                                                          RENDER_EXTERIORMODEL;
8258         if (!r_drawviewmodel.integer)
8259                 renderimask |= RENDER_VIEWMODEL;
8260         if (!r_drawexteriormodel.integer)
8261                 renderimask |= RENDER_EXTERIORMODEL;
8262         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8263         {
8264                 // worldmodel can check visibility
8265                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8266                 for (i = 0;i < r_refdef.scene.numentities;i++)
8267                 {
8268                         ent = r_refdef.scene.entities[i];
8269                         if (!(ent->flags & renderimask))
8270                         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)))
8271                         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))
8272                                 r_refdef.viewcache.entityvisible[i] = true;
8273                 }
8274                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8275                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8276                 {
8277                         for (i = 0;i < r_refdef.scene.numentities;i++)
8278                         {
8279                                 ent = r_refdef.scene.entities[i];
8280                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8281                                 {
8282                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8283                                         if (samples < 0)
8284                                                 continue; // temp entities do pvs only
8285                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8286                                                 ent->last_trace_visibility = realtime;
8287                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8288                                                 r_refdef.viewcache.entityvisible[i] = 0;
8289                                 }
8290                         }
8291                 }
8292         }
8293         else
8294         {
8295                 // no worldmodel or it can't check visibility
8296                 for (i = 0;i < r_refdef.scene.numentities;i++)
8297                 {
8298                         ent = r_refdef.scene.entities[i];
8299                         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));
8300                 }
8301         }
8302 }
8303
8304 /// only used if skyrendermasked, and normally returns false
8305 int R_DrawBrushModelsSky (void)
8306 {
8307         int i, sky;
8308         entity_render_t *ent;
8309
8310         sky = false;
8311         for (i = 0;i < r_refdef.scene.numentities;i++)
8312         {
8313                 if (!r_refdef.viewcache.entityvisible[i])
8314                         continue;
8315                 ent = r_refdef.scene.entities[i];
8316                 if (!ent->model || !ent->model->DrawSky)
8317                         continue;
8318                 ent->model->DrawSky(ent);
8319                 sky = true;
8320         }
8321         return sky;
8322 }
8323
8324 static void R_DrawNoModel(entity_render_t *ent);
8325 static void R_DrawModels(void)
8326 {
8327         int i;
8328         entity_render_t *ent;
8329
8330         for (i = 0;i < r_refdef.scene.numentities;i++)
8331         {
8332                 if (!r_refdef.viewcache.entityvisible[i])
8333                         continue;
8334                 ent = r_refdef.scene.entities[i];
8335                 r_refdef.stats.entities++;
8336                 if (ent->model && ent->model->Draw != NULL)
8337                         ent->model->Draw(ent);
8338                 else
8339                         R_DrawNoModel(ent);
8340         }
8341 }
8342
8343 static void R_DrawModelsDepth(void)
8344 {
8345         int i;
8346         entity_render_t *ent;
8347
8348         for (i = 0;i < r_refdef.scene.numentities;i++)
8349         {
8350                 if (!r_refdef.viewcache.entityvisible[i])
8351                         continue;
8352                 ent = r_refdef.scene.entities[i];
8353                 if (ent->model && ent->model->DrawDepth != NULL)
8354                         ent->model->DrawDepth(ent);
8355         }
8356 }
8357
8358 static void R_DrawModelsDebug(void)
8359 {
8360         int i;
8361         entity_render_t *ent;
8362
8363         for (i = 0;i < r_refdef.scene.numentities;i++)
8364         {
8365                 if (!r_refdef.viewcache.entityvisible[i])
8366                         continue;
8367                 ent = r_refdef.scene.entities[i];
8368                 if (ent->model && ent->model->DrawDebug != NULL)
8369                         ent->model->DrawDebug(ent);
8370         }
8371 }
8372
8373 static void R_DrawModelsAddWaterPlanes(void)
8374 {
8375         int i;
8376         entity_render_t *ent;
8377
8378         for (i = 0;i < r_refdef.scene.numentities;i++)
8379         {
8380                 if (!r_refdef.viewcache.entityvisible[i])
8381                         continue;
8382                 ent = r_refdef.scene.entities[i];
8383                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8384                         ent->model->DrawAddWaterPlanes(ent);
8385         }
8386 }
8387
8388 static void R_View_SetFrustum(const int *scissor)
8389 {
8390         int i;
8391         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8392         vec3_t forward, left, up, origin, v;
8393
8394         if(scissor)
8395         {
8396                 // flipped x coordinates (because x points left here)
8397                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8398                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8399
8400                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8401                 switch(vid.renderpath)
8402                 {
8403                         case RENDERPATH_D3D9:
8404                         case RENDERPATH_D3D10:
8405                         case RENDERPATH_D3D11:
8406                         case RENDERPATH_SOFT:
8407                                 // non-flipped y coordinates
8408                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8409                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8410                                 break;
8411                         case RENDERPATH_GL11:
8412                         case RENDERPATH_GL13:
8413                         case RENDERPATH_GL20:
8414                         case RENDERPATH_CGGL:
8415                         case RENDERPATH_GLES2:
8416                                 // non-flipped y coordinates
8417                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8418                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8419                                 break;
8420                 }
8421         }
8422
8423         // we can't trust r_refdef.view.forward and friends in reflected scenes
8424         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8425
8426 #if 0
8427         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8428         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8429         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8430         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8431         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8432         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8433         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8434         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8435         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8436         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8437         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8438         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8439 #endif
8440
8441 #if 0
8442         zNear = r_refdef.nearclip;
8443         nudge = 1.0 - 1.0 / (1<<23);
8444         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8445         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8446         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8447         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8448         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8449         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8450         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8451         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8452 #endif
8453
8454
8455
8456 #if 0
8457         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8458         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8459         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8460         r_refdef.view.frustum[0].dist = m[15] - m[12];
8461
8462         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8463         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8464         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8465         r_refdef.view.frustum[1].dist = m[15] + m[12];
8466
8467         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8468         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8469         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8470         r_refdef.view.frustum[2].dist = m[15] - m[13];
8471
8472         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8473         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8474         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8475         r_refdef.view.frustum[3].dist = m[15] + m[13];
8476
8477         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8478         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8479         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8480         r_refdef.view.frustum[4].dist = m[15] - m[14];
8481
8482         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8483         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8484         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8485         r_refdef.view.frustum[5].dist = m[15] + m[14];
8486 #endif
8487
8488         if (r_refdef.view.useperspective)
8489         {
8490                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8491                 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]);
8492                 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]);
8493                 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]);
8494                 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]);
8495
8496                 // then the normals from the corners relative to origin
8497                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8498                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8499                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8500                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8501
8502                 // in a NORMAL view, forward cross left == up
8503                 // in a REFLECTED view, forward cross left == down
8504                 // so our cross products above need to be adjusted for a left handed coordinate system
8505                 CrossProduct(forward, left, v);
8506                 if(DotProduct(v, up) < 0)
8507                 {
8508                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8509                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8510                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8511                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8512                 }
8513
8514                 // Leaving those out was a mistake, those were in the old code, and they
8515                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8516                 // I couldn't reproduce it after adding those normalizations. --blub
8517                 VectorNormalize(r_refdef.view.frustum[0].normal);
8518                 VectorNormalize(r_refdef.view.frustum[1].normal);
8519                 VectorNormalize(r_refdef.view.frustum[2].normal);
8520                 VectorNormalize(r_refdef.view.frustum[3].normal);
8521
8522                 // make the corners absolute
8523                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8524                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8525                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8526                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8527
8528                 // one more normal
8529                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8530
8531                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8532                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8533                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8534                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8535                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8536         }
8537         else
8538         {
8539                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8540                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8541                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8542                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8543                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8544                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8545                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8546                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8547                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8548                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8549         }
8550         r_refdef.view.numfrustumplanes = 5;
8551
8552         if (r_refdef.view.useclipplane)
8553         {
8554                 r_refdef.view.numfrustumplanes = 6;
8555                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8556         }
8557
8558         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8559                 PlaneClassify(r_refdef.view.frustum + i);
8560
8561         // LordHavoc: note to all quake engine coders, Quake had a special case
8562         // for 90 degrees which assumed a square view (wrong), so I removed it,
8563         // Quake2 has it disabled as well.
8564
8565         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8566         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8567         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8568         //PlaneClassify(&frustum[0]);
8569
8570         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8571         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8572         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8573         //PlaneClassify(&frustum[1]);
8574
8575         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8576         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8577         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8578         //PlaneClassify(&frustum[2]);
8579
8580         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8581         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8582         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8583         //PlaneClassify(&frustum[3]);
8584
8585         // nearclip plane
8586         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8587         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8588         //PlaneClassify(&frustum[4]);
8589 }
8590
8591 void R_View_UpdateWithScissor(const int *myscissor)
8592 {
8593         R_Main_ResizeViewCache();
8594         R_View_SetFrustum(myscissor);
8595         R_View_WorldVisibility(r_refdef.view.useclipplane);
8596         R_View_UpdateEntityVisible();
8597         R_View_UpdateEntityLighting();
8598 }
8599
8600 void R_View_Update(void)
8601 {
8602         R_Main_ResizeViewCache();
8603         R_View_SetFrustum(NULL);
8604         R_View_WorldVisibility(r_refdef.view.useclipplane);
8605         R_View_UpdateEntityVisible();
8606         R_View_UpdateEntityLighting();
8607 }
8608
8609 void R_SetupView(qboolean allowwaterclippingplane)
8610 {
8611         const float *customclipplane = NULL;
8612         float plane[4];
8613         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8614         {
8615                 // LordHavoc: couldn't figure out how to make this approach the
8616                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8617                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8618                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8619                         dist = r_refdef.view.clipplane.dist;
8620                 plane[0] = r_refdef.view.clipplane.normal[0];
8621                 plane[1] = r_refdef.view.clipplane.normal[1];
8622                 plane[2] = r_refdef.view.clipplane.normal[2];
8623                 plane[3] = dist;
8624                 customclipplane = plane;
8625         }
8626
8627         if (!r_refdef.view.useperspective)
8628                 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);
8629         else if (vid.stencil && r_useinfinitefarclip.integer)
8630                 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);
8631         else
8632                 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);
8633         R_SetViewport(&r_refdef.view.viewport);
8634 }
8635
8636 void R_EntityMatrix(const matrix4x4_t *matrix)
8637 {
8638         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8639         {
8640                 gl_modelmatrixchanged = false;
8641                 gl_modelmatrix = *matrix;
8642                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8643                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8644                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8645                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8646                 CHECKGLERROR
8647                 switch(vid.renderpath)
8648                 {
8649                 case RENDERPATH_D3D9:
8650 #ifdef SUPPORTD3D
8651                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8652                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8653 #endif
8654                         break;
8655                 case RENDERPATH_D3D10:
8656                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8657                         break;
8658                 case RENDERPATH_D3D11:
8659                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8660                         break;
8661                 case RENDERPATH_CGGL:
8662 #ifdef SUPPORTCG
8663                         CHECKCGERROR
8664                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8665                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8666                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8667 #endif
8668                         break;
8669                 case RENDERPATH_GL13:
8670                 case RENDERPATH_GL11:
8671                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8672                         break;
8673                 case RENDERPATH_SOFT:
8674                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
8675                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
8676                         break;
8677                 case RENDERPATH_GL20:
8678                 case RENDERPATH_GLES2:
8679                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8680                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8681                         break;
8682                 }
8683         }
8684 }
8685
8686 void R_ResetViewRendering2D(void)
8687 {
8688         r_viewport_t viewport;
8689         DrawQ_Finish();
8690
8691         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8692         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);
8693         R_SetViewport(&viewport);
8694         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8695         GL_Color(1, 1, 1, 1);
8696         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8697         GL_BlendFunc(GL_ONE, GL_ZERO);
8698         GL_ScissorTest(false);
8699         GL_DepthMask(false);
8700         GL_DepthRange(0, 1);
8701         GL_DepthTest(false);
8702         GL_DepthFunc(GL_LEQUAL);
8703         R_EntityMatrix(&identitymatrix);
8704         R_Mesh_ResetTextureState();
8705         GL_PolygonOffset(0, 0);
8706         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8707         switch(vid.renderpath)
8708         {
8709         case RENDERPATH_GL11:
8710         case RENDERPATH_GL13:
8711         case RENDERPATH_GL20:
8712         case RENDERPATH_CGGL:
8713         case RENDERPATH_GLES2:
8714                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8715                 break;
8716         case RENDERPATH_D3D9:
8717         case RENDERPATH_D3D10:
8718         case RENDERPATH_D3D11:
8719         case RENDERPATH_SOFT:
8720                 break;
8721         }
8722         GL_CullFace(GL_NONE);
8723 }
8724
8725 void R_ResetViewRendering3D(void)
8726 {
8727         DrawQ_Finish();
8728
8729         R_SetupView(true);
8730         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8731         GL_Color(1, 1, 1, 1);
8732         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8733         GL_BlendFunc(GL_ONE, GL_ZERO);
8734         GL_ScissorTest(true);
8735         GL_DepthMask(true);
8736         GL_DepthRange(0, 1);
8737         GL_DepthTest(true);
8738         GL_DepthFunc(GL_LEQUAL);
8739         R_EntityMatrix(&identitymatrix);
8740         R_Mesh_ResetTextureState();
8741         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8742         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8743         switch(vid.renderpath)
8744         {
8745         case RENDERPATH_GL11:
8746         case RENDERPATH_GL13:
8747         case RENDERPATH_GL20:
8748         case RENDERPATH_CGGL:
8749         case RENDERPATH_GLES2:
8750                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8751                 break;
8752         case RENDERPATH_D3D9:
8753         case RENDERPATH_D3D10:
8754         case RENDERPATH_D3D11:
8755         case RENDERPATH_SOFT:
8756                 break;
8757         }
8758         GL_CullFace(r_refdef.view.cullface_back);
8759 }
8760
8761 /*
8762 ================
8763 R_RenderView_UpdateViewVectors
8764 ================
8765 */
8766 static void R_RenderView_UpdateViewVectors(void)
8767 {
8768         // break apart the view matrix into vectors for various purposes
8769         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8770         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8771         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8772         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8773         // make an inverted copy of the view matrix for tracking sprites
8774         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8775 }
8776
8777 void R_RenderScene(void);
8778 void R_RenderWaterPlanes(void);
8779
8780 static void R_Water_StartFrame(void)
8781 {
8782         int i;
8783         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8784         r_waterstate_waterplane_t *p;
8785
8786         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8787                 return;
8788
8789         switch(vid.renderpath)
8790         {
8791         case RENDERPATH_GL20:
8792         case RENDERPATH_CGGL:
8793         case RENDERPATH_D3D9:
8794         case RENDERPATH_D3D10:
8795         case RENDERPATH_D3D11:
8796         case RENDERPATH_SOFT:
8797         case RENDERPATH_GLES2:
8798                 break;
8799         case RENDERPATH_GL13:
8800         case RENDERPATH_GL11:
8801                 return;
8802         }
8803
8804         // set waterwidth and waterheight to the water resolution that will be
8805         // used (often less than the screen resolution for faster rendering)
8806         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8807         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8808
8809         // calculate desired texture sizes
8810         // can't use water if the card does not support the texture size
8811         if (!r_water.integer || r_showsurfaces.integer)
8812                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8813         else if (vid.support.arb_texture_non_power_of_two)
8814         {
8815                 texturewidth = waterwidth;
8816                 textureheight = waterheight;
8817                 camerawidth = waterwidth;
8818                 cameraheight = waterheight;
8819         }
8820         else
8821         {
8822                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8823                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8824                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8825                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8826         }
8827
8828         // allocate textures as needed
8829         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8830         {
8831                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8832                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8833                 {
8834                         if (p->texture_refraction)
8835                                 R_FreeTexture(p->texture_refraction);
8836                         p->texture_refraction = NULL;
8837                         if (p->texture_reflection)
8838                                 R_FreeTexture(p->texture_reflection);
8839                         p->texture_reflection = NULL;
8840                         if (p->texture_camera)
8841                                 R_FreeTexture(p->texture_camera);
8842                         p->texture_camera = NULL;
8843                 }
8844                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8845                 r_waterstate.texturewidth = texturewidth;
8846                 r_waterstate.textureheight = textureheight;
8847                 r_waterstate.camerawidth = camerawidth;
8848                 r_waterstate.cameraheight = cameraheight;
8849         }
8850
8851         if (r_waterstate.texturewidth)
8852         {
8853                 r_waterstate.enabled = true;
8854
8855                 // when doing a reduced render (HDR) we want to use a smaller area
8856                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8857                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8858
8859                 // set up variables that will be used in shader setup
8860                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8861                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8862                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8863                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8864         }
8865
8866         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8867         r_waterstate.numwaterplanes = 0;
8868 }
8869
8870 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8871 {
8872         int triangleindex, planeindex;
8873         const int *e;
8874         vec3_t vert[3];
8875         vec3_t normal;
8876         vec3_t center;
8877         mplane_t plane;
8878         r_waterstate_waterplane_t *p;
8879         texture_t *t = R_GetCurrentTexture(surface->texture);
8880
8881         // just use the first triangle with a valid normal for any decisions
8882         VectorClear(normal);
8883         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8884         {
8885                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8886                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8887                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8888                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8889                 if (VectorLength2(normal) >= 0.001)
8890                         break;
8891         }
8892
8893         VectorCopy(normal, plane.normal);
8894         VectorNormalize(plane.normal);
8895         plane.dist = DotProduct(vert[0], plane.normal);
8896         PlaneClassify(&plane);
8897         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8898         {
8899                 // skip backfaces (except if nocullface is set)
8900                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8901                         return;
8902                 VectorNegate(plane.normal, plane.normal);
8903                 plane.dist *= -1;
8904                 PlaneClassify(&plane);
8905         }
8906
8907
8908         // find a matching plane if there is one
8909         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8910                 if(p->camera_entity == t->camera_entity)
8911                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8912                                 break;
8913         if (planeindex >= r_waterstate.maxwaterplanes)
8914                 return; // nothing we can do, out of planes
8915
8916         // if this triangle does not fit any known plane rendered this frame, add one
8917         if (planeindex >= r_waterstate.numwaterplanes)
8918         {
8919                 // store the new plane
8920                 r_waterstate.numwaterplanes++;
8921                 p->plane = plane;
8922                 // clear materialflags and pvs
8923                 p->materialflags = 0;
8924                 p->pvsvalid = false;
8925                 p->camera_entity = t->camera_entity;
8926                 VectorCopy(surface->mins, p->mins);
8927                 VectorCopy(surface->maxs, p->maxs);
8928         }
8929         else
8930         {
8931                 // merge mins/maxs
8932                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8933                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8934                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8935                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8936                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8937                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8938         }
8939         // merge this surface's materialflags into the waterplane
8940         p->materialflags |= t->currentmaterialflags;
8941         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8942         {
8943                 // merge this surface's PVS into the waterplane
8944                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8945                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8946                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8947                 {
8948                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8949                         p->pvsvalid = true;
8950                 }
8951         }
8952 }
8953
8954 static void R_Water_ProcessPlanes(void)
8955 {
8956         int myscissor[4];
8957         r_refdef_view_t originalview;
8958         r_refdef_view_t myview;
8959         int planeindex;
8960         r_waterstate_waterplane_t *p;
8961         vec3_t visorigin;
8962
8963         originalview = r_refdef.view;
8964
8965         // make sure enough textures are allocated
8966         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8967         {
8968                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8969                 {
8970                         if (!p->texture_refraction)
8971                                 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);
8972                         if (!p->texture_refraction)
8973                                 goto error;
8974                 }
8975                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8976                 {
8977                         if (!p->texture_camera)
8978                                 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);
8979                         if (!p->texture_camera)
8980                                 goto error;
8981                 }
8982
8983                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8984                 {
8985                         if (!p->texture_reflection)
8986                                 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);
8987                         if (!p->texture_reflection)
8988                                 goto error;
8989                 }
8990         }
8991
8992         // render views
8993         r_refdef.view = originalview;
8994         r_refdef.view.showdebug = false;
8995         r_refdef.view.width = r_waterstate.waterwidth;
8996         r_refdef.view.height = r_waterstate.waterheight;
8997         r_refdef.view.useclipplane = true;
8998         myview = r_refdef.view;
8999         r_waterstate.renderingscene = true;
9000         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9001         {
9002                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
9003                 {
9004                         r_refdef.view = myview;
9005                         if(r_water_scissormode.integer)
9006                         {
9007                                 R_SetupView(true);
9008                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
9009                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
9010                         }
9011
9012                         // render reflected scene and copy into texture
9013                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
9014                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
9015                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
9016                         r_refdef.view.clipplane = p->plane;
9017
9018                         // reverse the cullface settings for this render
9019                         r_refdef.view.cullface_front = GL_FRONT;
9020                         r_refdef.view.cullface_back = GL_BACK;
9021                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
9022                         {
9023                                 r_refdef.view.usecustompvs = true;
9024                                 if (p->pvsvalid)
9025                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
9026                                 else
9027                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
9028                         }
9029
9030                         R_ResetViewRendering3D();
9031                         R_ClearScreen(r_refdef.fogenabled);
9032                         if(r_water_scissormode.integer & 2)
9033                                 R_View_UpdateWithScissor(myscissor);
9034                         else
9035                                 R_View_Update();
9036                         if(r_water_scissormode.integer & 1)
9037                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
9038                         R_RenderScene();
9039
9040                         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);
9041                 }
9042
9043                 // render the normal view scene and copy into texture
9044                 // (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)
9045                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
9046                 {
9047                         r_refdef.view = myview;
9048                         if(r_water_scissormode.integer)
9049                         {
9050                                 R_SetupView(true);
9051                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
9052                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
9053                         }
9054
9055                         r_waterstate.renderingrefraction = true;
9056
9057                         r_refdef.view.clipplane = p->plane;
9058                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
9059                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
9060
9061                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
9062                         {
9063                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
9064                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
9065                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
9066                                 R_RenderView_UpdateViewVectors();
9067                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
9068                                 {
9069                                         r_refdef.view.usecustompvs = true;
9070                                         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);
9071                                 }
9072                         }
9073
9074                         PlaneClassify(&r_refdef.view.clipplane);
9075
9076                         R_ResetViewRendering3D();
9077                         R_ClearScreen(r_refdef.fogenabled);
9078                         if(r_water_scissormode.integer & 2)
9079                                 R_View_UpdateWithScissor(myscissor);
9080                         else
9081                                 R_View_Update();
9082                         if(r_water_scissormode.integer & 1)
9083                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
9084                         R_RenderScene();
9085
9086                         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);
9087                         r_waterstate.renderingrefraction = false;
9088                 }
9089                 else if (p->materialflags & MATERIALFLAG_CAMERA)
9090                 {
9091                         r_refdef.view = myview;
9092
9093                         r_refdef.view.clipplane = p->plane;
9094                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
9095                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
9096
9097                         r_refdef.view.width = r_waterstate.camerawidth;
9098                         r_refdef.view.height = r_waterstate.cameraheight;
9099                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
9100                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
9101
9102                         if(p->camera_entity)
9103                         {
9104                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
9105                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
9106                         }
9107
9108                         // note: all of the view is used for displaying... so
9109                         // there is no use in scissoring
9110
9111                         // reverse the cullface settings for this render
9112                         r_refdef.view.cullface_front = GL_FRONT;
9113                         r_refdef.view.cullface_back = GL_BACK;
9114                         // also reverse the view matrix
9115                         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
9116                         R_RenderView_UpdateViewVectors();
9117                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
9118                         {
9119                                 r_refdef.view.usecustompvs = true;
9120                                 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);
9121                         }
9122                         
9123                         // camera needs no clipplane
9124                         r_refdef.view.useclipplane = false;
9125
9126                         PlaneClassify(&r_refdef.view.clipplane);
9127
9128                         R_ResetViewRendering3D();
9129                         R_ClearScreen(r_refdef.fogenabled);
9130                         R_View_Update();
9131                         R_RenderScene();
9132
9133                         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);
9134                         r_waterstate.renderingrefraction = false;
9135                 }
9136
9137         }
9138         r_waterstate.renderingscene = false;
9139         r_refdef.view = originalview;
9140         R_ResetViewRendering3D();
9141         R_ClearScreen(r_refdef.fogenabled);
9142         R_View_Update();
9143         return;
9144 error:
9145         r_refdef.view = originalview;
9146         r_waterstate.renderingscene = false;
9147         Cvar_SetValueQuick(&r_water, 0);
9148         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
9149         return;
9150 }
9151
9152 void R_Bloom_StartFrame(void)
9153 {
9154         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
9155
9156         switch(vid.renderpath)
9157         {
9158         case RENDERPATH_GL20:
9159         case RENDERPATH_CGGL:
9160         case RENDERPATH_D3D9:
9161         case RENDERPATH_D3D10:
9162         case RENDERPATH_D3D11:
9163         case RENDERPATH_SOFT:
9164         case RENDERPATH_GLES2:
9165                 break;
9166         case RENDERPATH_GL13:
9167         case RENDERPATH_GL11:
9168                 return;
9169         }
9170
9171         // set bloomwidth and bloomheight to the bloom resolution that will be
9172         // used (often less than the screen resolution for faster rendering)
9173         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
9174         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
9175         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
9176         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
9177         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
9178
9179         // calculate desired texture sizes
9180         if (vid.support.arb_texture_non_power_of_two)
9181         {
9182                 screentexturewidth = r_refdef.view.width;
9183                 screentextureheight = r_refdef.view.height;
9184                 bloomtexturewidth = r_bloomstate.bloomwidth;
9185                 bloomtextureheight = r_bloomstate.bloomheight;
9186         }
9187         else
9188         {
9189                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
9190                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
9191                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
9192                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
9193         }
9194
9195         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))
9196         {
9197                 Cvar_SetValueQuick(&r_hdr, 0);
9198                 Cvar_SetValueQuick(&r_bloom, 0);
9199                 Cvar_SetValueQuick(&r_motionblur, 0);
9200                 Cvar_SetValueQuick(&r_damageblur, 0);
9201         }
9202
9203         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)))
9204                 screentexturewidth = screentextureheight = 0;
9205         if (!r_hdr.integer && !r_bloom.integer)
9206                 bloomtexturewidth = bloomtextureheight = 0;
9207
9208         // allocate textures as needed
9209         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
9210         {
9211                 if (r_bloomstate.texture_screen)
9212                         R_FreeTexture(r_bloomstate.texture_screen);
9213                 r_bloomstate.texture_screen = NULL;
9214                 r_bloomstate.screentexturewidth = screentexturewidth;
9215                 r_bloomstate.screentextureheight = screentextureheight;
9216                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
9217                         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);
9218         }
9219         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
9220         {
9221                 if (r_bloomstate.texture_bloom)
9222                         R_FreeTexture(r_bloomstate.texture_bloom);
9223                 r_bloomstate.texture_bloom = NULL;
9224                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
9225                 r_bloomstate.bloomtextureheight = bloomtextureheight;
9226                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
9227                         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);
9228         }
9229
9230         // when doing a reduced render (HDR) we want to use a smaller area
9231         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
9232         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
9233         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
9234         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
9235         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
9236
9237         // set up a texcoord array for the full resolution screen image
9238         // (we have to keep this around to copy back during final render)
9239         r_bloomstate.screentexcoord2f[0] = 0;
9240         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
9241         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
9242         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
9243         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
9244         r_bloomstate.screentexcoord2f[5] = 0;
9245         r_bloomstate.screentexcoord2f[6] = 0;
9246         r_bloomstate.screentexcoord2f[7] = 0;
9247
9248         // set up a texcoord array for the reduced resolution bloom image
9249         // (which will be additive blended over the screen image)
9250         r_bloomstate.bloomtexcoord2f[0] = 0;
9251         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9252         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9253         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9254         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9255         r_bloomstate.bloomtexcoord2f[5] = 0;
9256         r_bloomstate.bloomtexcoord2f[6] = 0;
9257         r_bloomstate.bloomtexcoord2f[7] = 0;
9258
9259         switch(vid.renderpath)
9260         {
9261         case RENDERPATH_GL11:
9262         case RENDERPATH_GL13:
9263         case RENDERPATH_GL20:
9264         case RENDERPATH_CGGL:
9265         case RENDERPATH_SOFT:
9266         case RENDERPATH_GLES2:
9267                 break;
9268         case RENDERPATH_D3D9:
9269         case RENDERPATH_D3D10:
9270         case RENDERPATH_D3D11:
9271                 {
9272                         int i;
9273                         for (i = 0;i < 4;i++)
9274                         {
9275                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
9276                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
9277                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
9278                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
9279                         }
9280                 }
9281                 break;
9282         }
9283
9284         if (r_hdr.integer || r_bloom.integer)
9285         {
9286                 r_bloomstate.enabled = true;
9287                 r_bloomstate.hdr = r_hdr.integer != 0;
9288         }
9289
9290         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);
9291 }
9292
9293 void R_Bloom_CopyBloomTexture(float colorscale)
9294 {
9295         r_refdef.stats.bloom++;
9296
9297         // scale down screen texture to the bloom texture size
9298         CHECKGLERROR
9299         R_SetViewport(&r_bloomstate.viewport);
9300         GL_BlendFunc(GL_ONE, GL_ZERO);
9301         GL_Color(colorscale, colorscale, colorscale, 1);
9302         // 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...
9303         switch(vid.renderpath)
9304         {
9305         case RENDERPATH_GL11:
9306         case RENDERPATH_GL13:
9307         case RENDERPATH_GL20:
9308         case RENDERPATH_CGGL:
9309         case RENDERPATH_SOFT:
9310         case RENDERPATH_GLES2:
9311                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9312                 break;
9313         case RENDERPATH_D3D9:
9314         case RENDERPATH_D3D10:
9315         case RENDERPATH_D3D11:
9316                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9317                 break;
9318         }
9319         // TODO: do boxfilter scale-down in shader?
9320         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9321         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9322         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9323
9324         // we now have a bloom image in the framebuffer
9325         // copy it into the bloom image texture for later processing
9326         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);
9327         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9328 }
9329
9330 void R_Bloom_CopyHDRTexture(void)
9331 {
9332         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);
9333         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9334 }
9335
9336 void R_Bloom_MakeTexture(void)
9337 {
9338         int x, range, dir;
9339         float xoffset, yoffset, r, brighten;
9340
9341         r_refdef.stats.bloom++;
9342
9343         R_ResetViewRendering2D();
9344
9345         // we have a bloom image in the framebuffer
9346         CHECKGLERROR
9347         R_SetViewport(&r_bloomstate.viewport);
9348
9349         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9350         {
9351                 x *= 2;
9352                 r = bound(0, r_bloom_colorexponent.value / x, 1);
9353                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9354                 GL_Color(r,r,r,1);
9355                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9356                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9357                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9358                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9359
9360                 // copy the vertically blurred bloom view to a texture
9361                 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);
9362                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9363         }
9364
9365         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9366         brighten = r_bloom_brighten.value;
9367         if (r_hdr.integer)
9368                 brighten *= r_hdr_range.value;
9369         brighten = sqrt(brighten);
9370         if(range >= 1)
9371                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9372         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9373
9374         for (dir = 0;dir < 2;dir++)
9375         {
9376                 // blend on at multiple vertical offsets to achieve a vertical blur
9377                 // TODO: do offset blends using GLSL
9378                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9379                 GL_BlendFunc(GL_ONE, GL_ZERO);
9380                 for (x = -range;x <= range;x++)
9381                 {
9382                         if (!dir){xoffset = 0;yoffset = x;}
9383                         else {xoffset = x;yoffset = 0;}
9384                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9385                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9386                         // compute a texcoord array with the specified x and y offset
9387                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9388                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9389                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9390                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9391                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9392                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9393                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9394                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9395                         // this r value looks like a 'dot' particle, fading sharply to
9396                         // black at the edges
9397                         // (probably not realistic but looks good enough)
9398                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9399                         //r = brighten/(range*2+1);
9400                         r = brighten / (range * 2 + 1);
9401                         if(range >= 1)
9402                                 r *= (1 - x*x/(float)(range*range));
9403                         GL_Color(r, r, r, 1);
9404                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9405                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9406                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9407                         GL_BlendFunc(GL_ONE, GL_ONE);
9408                 }
9409
9410                 // copy the vertically blurred bloom view to a texture
9411                 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);
9412                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9413         }
9414 }
9415
9416 void R_HDR_RenderBloomTexture(void)
9417 {
9418         int oldwidth, oldheight;
9419         float oldcolorscale;
9420         qboolean oldwaterstate;
9421
9422         oldwaterstate = r_waterstate.enabled;
9423         oldcolorscale = r_refdef.view.colorscale;
9424         oldwidth = r_refdef.view.width;
9425         oldheight = r_refdef.view.height;
9426         r_refdef.view.width = r_bloomstate.bloomwidth;
9427         r_refdef.view.height = r_bloomstate.bloomheight;
9428
9429         if(r_hdr.integer < 2)
9430                 r_waterstate.enabled = false;
9431
9432         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9433         // TODO: add exposure compensation features
9434         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9435
9436         r_refdef.view.showdebug = false;
9437         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9438
9439         R_ResetViewRendering3D();
9440
9441         R_ClearScreen(r_refdef.fogenabled);
9442         if (r_timereport_active)
9443                 R_TimeReport("HDRclear");
9444
9445         R_View_Update();
9446         if (r_timereport_active)
9447                 R_TimeReport("visibility");
9448
9449         // only do secondary renders with HDR if r_hdr is 2 or higher
9450         r_waterstate.numwaterplanes = 0;
9451         if (r_waterstate.enabled)
9452                 R_RenderWaterPlanes();
9453
9454         r_refdef.view.showdebug = true;
9455         R_RenderScene();
9456         r_waterstate.numwaterplanes = 0;
9457
9458         R_ResetViewRendering2D();
9459
9460         R_Bloom_CopyHDRTexture();
9461         R_Bloom_MakeTexture();
9462
9463         // restore the view settings
9464         r_waterstate.enabled = oldwaterstate;
9465         r_refdef.view.width = oldwidth;
9466         r_refdef.view.height = oldheight;
9467         r_refdef.view.colorscale = oldcolorscale;
9468
9469         R_ResetViewRendering3D();
9470
9471         R_ClearScreen(r_refdef.fogenabled);
9472         if (r_timereport_active)
9473                 R_TimeReport("viewclear");
9474 }
9475
9476 static void R_BlendView(void)
9477 {
9478         unsigned int permutation;
9479         float uservecs[4][4];
9480
9481         switch (vid.renderpath)
9482         {
9483         case RENDERPATH_GL20:
9484         case RENDERPATH_CGGL:
9485         case RENDERPATH_D3D9:
9486         case RENDERPATH_D3D10:
9487         case RENDERPATH_D3D11:
9488         case RENDERPATH_SOFT:
9489         case RENDERPATH_GLES2:
9490                 permutation =
9491                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9492                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9493                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9494                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9495                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9496
9497                 if (r_bloomstate.texture_screen)
9498                 {
9499                         // make sure the buffer is available
9500                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9501
9502                         R_ResetViewRendering2D();
9503
9504                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9505                         {
9506                                 // declare variables
9507                                 float speed;
9508                                 static float avgspeed;
9509
9510                                 speed = VectorLength(cl.movement_velocity);
9511
9512                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9513                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9514
9515                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9516                                 speed = bound(0, speed, 1);
9517                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9518
9519                                 // calculate values into a standard alpha
9520                                 cl.motionbluralpha = 1 - exp(-
9521                                                 (
9522                                                  (r_motionblur.value * speed / 80)
9523                                                  +
9524                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9525                                                 )
9526                                                 /
9527                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9528                                            );
9529
9530                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9531                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9532                                 // apply the blur
9533                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9534                                 {
9535                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9536                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9537                                         switch(vid.renderpath)
9538                                         {
9539                                         case RENDERPATH_GL11:
9540                                         case RENDERPATH_GL13:
9541                                         case RENDERPATH_GL20:
9542                                         case RENDERPATH_CGGL:
9543                                         case RENDERPATH_SOFT:
9544                                         case RENDERPATH_GLES2:
9545                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9546                                                 break;
9547                                         case RENDERPATH_D3D9:
9548                                         case RENDERPATH_D3D10:
9549                                         case RENDERPATH_D3D11:
9550                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9551                                                 break;
9552                                         }
9553                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9554                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9555                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9556                                 }
9557                         }
9558
9559                         // copy view into the screen texture
9560                         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);
9561                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9562                 }
9563                 else if (!r_bloomstate.texture_bloom)
9564                 {
9565                         // we may still have to do view tint...
9566                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9567                         {
9568                                 // apply a color tint to the whole view
9569                                 R_ResetViewRendering2D();
9570                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9571                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9572                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9573                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9574                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9575                         }
9576                         break; // no screen processing, no bloom, skip it
9577                 }
9578
9579                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9580                 {
9581                         // render simple bloom effect
9582                         // copy the screen and shrink it and darken it for the bloom process
9583                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9584                         // make the bloom texture
9585                         R_Bloom_MakeTexture();
9586                 }
9587
9588 #if _MSC_VER >= 1400
9589 #define sscanf sscanf_s
9590 #endif
9591                 memset(uservecs, 0, sizeof(uservecs));
9592                 if (r_glsl_postprocess_uservec1_enable.integer)
9593                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9594                 if (r_glsl_postprocess_uservec2_enable.integer)
9595                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9596                 if (r_glsl_postprocess_uservec3_enable.integer)
9597                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9598                 if (r_glsl_postprocess_uservec4_enable.integer)
9599                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9600
9601                 R_ResetViewRendering2D();
9602                 GL_Color(1, 1, 1, 1);
9603                 GL_BlendFunc(GL_ONE, GL_ZERO);
9604
9605                 switch(vid.renderpath)
9606                 {
9607                 case RENDERPATH_GL20:
9608                 case RENDERPATH_GLES2:
9609                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9610                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9611                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
9612                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
9613                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
9614                         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]);
9615                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9616                         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]);
9617                         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]);
9618                         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]);
9619                         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]);
9620                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9621                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9622                         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);
9623                         break;
9624                 case RENDERPATH_CGGL:
9625 #ifdef SUPPORTCG
9626                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9627                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9628                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9629                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9630                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9631                         if (r_cg_permutation->fp_ViewTintColor     ) cgGLSetParameter4f(     r_cg_permutation->fp_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);CHECKCGERROR
9632                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9633                         if (r_cg_permutation->fp_UserVec1          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);CHECKCGERROR
9634                         if (r_cg_permutation->fp_UserVec2          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);CHECKCGERROR
9635                         if (r_cg_permutation->fp_UserVec3          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);CHECKCGERROR
9636                         if (r_cg_permutation->fp_UserVec4          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);CHECKCGERROR
9637                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9638                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9639                         if (r_cg_permutation->fp_BloomColorSubtract   ) cgGLSetParameter4f(r_cg_permutation->fp_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9640 #endif
9641                         break;
9642                 case RENDERPATH_D3D9:
9643 #ifdef SUPPORTD3D
9644                         // 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...
9645                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9646                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9647                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9648                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9649                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9650                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9651                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9652                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9653                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9654                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9655                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9656                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9657                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9658                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9659 #endif
9660                         break;
9661                 case RENDERPATH_D3D10:
9662                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9663                         break;
9664                 case RENDERPATH_D3D11:
9665                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9666                         break;
9667                 case RENDERPATH_SOFT:
9668                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9669                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
9670                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9671                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9672                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9673                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9674                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9675                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9676                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9677                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9678                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9679                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
9680                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9681                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9682                         break;
9683                 default:
9684                         break;
9685                 }
9686                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9687                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9688                 break;
9689         case RENDERPATH_GL13:
9690         case RENDERPATH_GL11:
9691                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9692                 {
9693                         // apply a color tint to the whole view
9694                         R_ResetViewRendering2D();
9695                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9696                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9697                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9698                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9699                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9700                 }
9701                 break;
9702         }
9703 }
9704
9705 matrix4x4_t r_waterscrollmatrix;
9706
9707 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9708 {
9709         if (r_refdef.fog_density)
9710         {
9711                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9712                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9713                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9714
9715                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9716                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9717                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9718                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9719
9720                 {
9721                         vec3_t fogvec;
9722                         VectorCopy(r_refdef.fogcolor, fogvec);
9723                         //   color.rgb *= ContrastBoost * SceneBrightness;
9724                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9725                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9726                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9727                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9728                 }
9729         }
9730 }
9731
9732 void R_UpdateVariables(void)
9733 {
9734         R_Textures_Frame();
9735
9736         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9737
9738         r_refdef.farclip = r_farclip_base.value;
9739         if (r_refdef.scene.worldmodel)
9740                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9741         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9742
9743         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9744                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9745         r_refdef.polygonfactor = 0;
9746         r_refdef.polygonoffset = 0;
9747         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9748         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9749
9750         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9751         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9752         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
9753         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9754         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9755         if (FAKELIGHT_ENABLED)
9756         {
9757                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9758         }
9759         if (r_showsurfaces.integer)
9760         {
9761                 r_refdef.scene.rtworld = false;
9762                 r_refdef.scene.rtworldshadows = false;
9763                 r_refdef.scene.rtdlight = false;
9764                 r_refdef.scene.rtdlightshadows = false;
9765                 r_refdef.lightmapintensity = 0;
9766         }
9767
9768         if (gamemode == GAME_NEHAHRA)
9769         {
9770                 if (gl_fogenable.integer)
9771                 {
9772                         r_refdef.oldgl_fogenable = true;
9773                         r_refdef.fog_density = gl_fogdensity.value;
9774                         r_refdef.fog_red = gl_fogred.value;
9775                         r_refdef.fog_green = gl_foggreen.value;
9776                         r_refdef.fog_blue = gl_fogblue.value;
9777                         r_refdef.fog_alpha = 1;
9778                         r_refdef.fog_start = 0;
9779                         r_refdef.fog_end = gl_skyclip.value;
9780                         r_refdef.fog_height = 1<<30;
9781                         r_refdef.fog_fadedepth = 128;
9782                 }
9783                 else if (r_refdef.oldgl_fogenable)
9784                 {
9785                         r_refdef.oldgl_fogenable = false;
9786                         r_refdef.fog_density = 0;
9787                         r_refdef.fog_red = 0;
9788                         r_refdef.fog_green = 0;
9789                         r_refdef.fog_blue = 0;
9790                         r_refdef.fog_alpha = 0;
9791                         r_refdef.fog_start = 0;
9792                         r_refdef.fog_end = 0;
9793                         r_refdef.fog_height = 1<<30;
9794                         r_refdef.fog_fadedepth = 128;
9795                 }
9796         }
9797
9798         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9799         r_refdef.fog_start = max(0, r_refdef.fog_start);
9800         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9801
9802         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9803
9804         if (r_refdef.fog_density && r_drawfog.integer)
9805         {
9806                 r_refdef.fogenabled = true;
9807                 // this is the point where the fog reaches 0.9986 alpha, which we
9808                 // consider a good enough cutoff point for the texture
9809                 // (0.9986 * 256 == 255.6)
9810                 if (r_fog_exp2.integer)
9811                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9812                 else
9813                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9814                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9815                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9816                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9817                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9818                         R_BuildFogHeightTexture();
9819                 // fog color was already set
9820                 // update the fog texture
9821                 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)
9822                         R_BuildFogTexture();
9823                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9824                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9825         }
9826         else
9827                 r_refdef.fogenabled = false;
9828
9829         switch(vid.renderpath)
9830         {
9831         case RENDERPATH_GL20:
9832         case RENDERPATH_CGGL:
9833         case RENDERPATH_D3D9:
9834         case RENDERPATH_D3D10:
9835         case RENDERPATH_D3D11:
9836         case RENDERPATH_SOFT:
9837         case RENDERPATH_GLES2:
9838                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9839                 {
9840                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9841                         {
9842                                 // build GLSL gamma texture
9843 #define RAMPWIDTH 256
9844                                 unsigned short ramp[RAMPWIDTH * 3];
9845                                 unsigned char rampbgr[RAMPWIDTH][4];
9846                                 int i;
9847
9848                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9849
9850                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9851                                 for(i = 0; i < RAMPWIDTH; ++i)
9852                                 {
9853                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9854                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9855                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9856                                         rampbgr[i][3] = 0;
9857                                 }
9858                                 if (r_texture_gammaramps)
9859                                 {
9860                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9861                                 }
9862                                 else
9863                                 {
9864                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9865                                 }
9866                         }
9867                 }
9868                 else
9869                 {
9870                         // remove GLSL gamma texture
9871                 }
9872                 break;
9873         case RENDERPATH_GL13:
9874         case RENDERPATH_GL11:
9875                 break;
9876         }
9877 }
9878
9879 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9880 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9881 /*
9882 ================
9883 R_SelectScene
9884 ================
9885 */
9886 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9887         if( scenetype != r_currentscenetype ) {
9888                 // store the old scenetype
9889                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9890                 r_currentscenetype = scenetype;
9891                 // move in the new scene
9892                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9893         }
9894 }
9895
9896 /*
9897 ================
9898 R_GetScenePointer
9899 ================
9900 */
9901 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9902 {
9903         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9904         if( scenetype == r_currentscenetype ) {
9905                 return &r_refdef.scene;
9906         } else {
9907                 return &r_scenes_store[ scenetype ];
9908         }
9909 }
9910
9911 /*
9912 ================
9913 R_RenderView
9914 ================
9915 */
9916 int dpsoftrast_test;
9917 void R_RenderView(void)
9918 {
9919         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9920
9921         dpsoftrast_test = r_test.integer;
9922
9923         if (r_timereport_active)
9924                 R_TimeReport("start");
9925         r_textureframe++; // used only by R_GetCurrentTexture
9926         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9927
9928         if(R_CompileShader_CheckStaticParms())
9929                 R_GLSL_Restart_f();
9930
9931         if (!r_drawentities.integer)
9932                 r_refdef.scene.numentities = 0;
9933
9934         R_AnimCache_ClearCache();
9935         R_FrameData_NewFrame();
9936
9937         /* adjust for stereo display */
9938         if(R_Stereo_Active())
9939         {
9940                 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);
9941                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9942         }
9943
9944         if (r_refdef.view.isoverlay)
9945         {
9946                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9947                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9948                 R_TimeReport("depthclear");
9949
9950                 r_refdef.view.showdebug = false;
9951
9952                 r_waterstate.enabled = false;
9953                 r_waterstate.numwaterplanes = 0;
9954
9955                 R_RenderScene();
9956
9957                 r_refdef.view.matrix = originalmatrix;
9958
9959                 CHECKGLERROR
9960                 return;
9961         }
9962
9963         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9964         {
9965                 r_refdef.view.matrix = originalmatrix;
9966                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9967         }
9968
9969         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9970
9971         R_RenderView_UpdateViewVectors();
9972
9973         R_Shadow_UpdateWorldLightSelection();
9974
9975         R_Bloom_StartFrame();
9976         R_Water_StartFrame();
9977
9978         CHECKGLERROR
9979         if (r_timereport_active)
9980                 R_TimeReport("viewsetup");
9981
9982         R_ResetViewRendering3D();
9983
9984         if (r_refdef.view.clear || r_refdef.fogenabled)
9985         {
9986                 R_ClearScreen(r_refdef.fogenabled);
9987                 if (r_timereport_active)
9988                         R_TimeReport("viewclear");
9989         }
9990         r_refdef.view.clear = true;
9991
9992         // this produces a bloom texture to be used in R_BlendView() later
9993         if (r_hdr.integer && r_bloomstate.bloomwidth)
9994         {
9995                 R_HDR_RenderBloomTexture();
9996                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9997                 r_textureframe++; // used only by R_GetCurrentTexture
9998         }
9999
10000         r_refdef.view.showdebug = true;
10001
10002         R_View_Update();
10003         if (r_timereport_active)
10004                 R_TimeReport("visibility");
10005
10006         r_waterstate.numwaterplanes = 0;
10007         if (r_waterstate.enabled)
10008                 R_RenderWaterPlanes();
10009
10010         R_RenderScene();
10011         r_waterstate.numwaterplanes = 0;
10012
10013         R_BlendView();
10014         if (r_timereport_active)
10015                 R_TimeReport("blendview");
10016
10017         GL_Scissor(0, 0, vid.width, vid.height);
10018         GL_ScissorTest(false);
10019
10020         r_refdef.view.matrix = originalmatrix;
10021
10022         CHECKGLERROR
10023 }
10024
10025 void R_RenderWaterPlanes(void)
10026 {
10027         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
10028         {
10029                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
10030                 if (r_timereport_active)
10031                         R_TimeReport("waterworld");
10032         }
10033
10034         // don't let sound skip if going slow
10035         if (r_refdef.scene.extraupdate)
10036                 S_ExtraUpdate ();
10037
10038         R_DrawModelsAddWaterPlanes();
10039         if (r_timereport_active)
10040                 R_TimeReport("watermodels");
10041
10042         if (r_waterstate.numwaterplanes)
10043         {
10044                 R_Water_ProcessPlanes();
10045                 if (r_timereport_active)
10046                         R_TimeReport("waterscenes");
10047         }
10048 }
10049
10050 extern void R_DrawLightningBeams (void);
10051 extern void VM_CL_AddPolygonsToMeshQueue (void);
10052 extern void R_DrawPortals (void);
10053 extern cvar_t cl_locs_show;
10054 static void R_DrawLocs(void);
10055 static void R_DrawEntityBBoxes(void);
10056 static void R_DrawModelDecals(void);
10057 extern void R_DrawModelShadows(void);
10058 extern void R_DrawModelShadowMaps(void);
10059 extern cvar_t cl_decals_newsystem;
10060 extern qboolean r_shadow_usingdeferredprepass;
10061 void R_RenderScene(void)
10062 {
10063         qboolean shadowmapping = false;
10064
10065         if (r_timereport_active)
10066                 R_TimeReport("beginscene");
10067
10068         r_refdef.stats.renders++;
10069
10070         R_UpdateFogColor();
10071
10072         // don't let sound skip if going slow
10073         if (r_refdef.scene.extraupdate)
10074                 S_ExtraUpdate ();
10075
10076         R_MeshQueue_BeginScene();
10077
10078         R_SkyStartFrame();
10079
10080         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);
10081
10082         if (r_timereport_active)
10083                 R_TimeReport("skystartframe");
10084
10085         if (cl.csqc_vidvars.drawworld)
10086         {
10087                 // don't let sound skip if going slow
10088                 if (r_refdef.scene.extraupdate)
10089                         S_ExtraUpdate ();
10090
10091                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
10092                 {
10093                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
10094                         if (r_timereport_active)
10095                                 R_TimeReport("worldsky");
10096                 }
10097
10098                 if (R_DrawBrushModelsSky() && r_timereport_active)
10099                         R_TimeReport("bmodelsky");
10100
10101                 if (skyrendermasked && skyrenderlater)
10102                 {
10103                         // we have to force off the water clipping plane while rendering sky
10104                         R_SetupView(false);
10105                         R_Sky();
10106                         R_SetupView(true);
10107                         if (r_timereport_active)
10108                                 R_TimeReport("sky");
10109                 }
10110         }
10111
10112         R_AnimCache_CacheVisibleEntities();
10113         if (r_timereport_active)
10114                 R_TimeReport("animation");
10115
10116         R_Shadow_PrepareLights();
10117         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
10118                 R_Shadow_PrepareModelShadows();
10119         if (r_timereport_active)
10120                 R_TimeReport("preparelights");
10121
10122         if (R_Shadow_ShadowMappingEnabled())
10123                 shadowmapping = true;
10124
10125         if (r_shadow_usingdeferredprepass)
10126                 R_Shadow_DrawPrepass();
10127
10128         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
10129         {
10130                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
10131                 if (r_timereport_active)
10132                         R_TimeReport("worlddepth");
10133         }
10134         if (r_depthfirst.integer >= 2)
10135         {
10136                 R_DrawModelsDepth();
10137                 if (r_timereport_active)
10138                         R_TimeReport("modeldepth");
10139         }
10140
10141         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
10142         {
10143                 R_DrawModelShadowMaps();
10144                 R_ResetViewRendering3D();
10145                 // don't let sound skip if going slow
10146                 if (r_refdef.scene.extraupdate)
10147                         S_ExtraUpdate ();
10148         }
10149
10150         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
10151         {
10152                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
10153                 if (r_timereport_active)
10154                         R_TimeReport("world");
10155         }
10156
10157         // don't let sound skip if going slow
10158         if (r_refdef.scene.extraupdate)
10159                 S_ExtraUpdate ();
10160
10161         R_DrawModels();
10162         if (r_timereport_active)
10163                 R_TimeReport("models");
10164
10165         // don't let sound skip if going slow
10166         if (r_refdef.scene.extraupdate)
10167                 S_ExtraUpdate ();
10168
10169         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
10170         {
10171                 R_DrawModelShadows();
10172                 R_ResetViewRendering3D();
10173                 // don't let sound skip if going slow
10174                 if (r_refdef.scene.extraupdate)
10175                         S_ExtraUpdate ();
10176         }
10177
10178         if (!r_shadow_usingdeferredprepass)
10179         {
10180                 R_Shadow_DrawLights();
10181                 if (r_timereport_active)
10182                         R_TimeReport("rtlights");
10183         }
10184
10185         // don't let sound skip if going slow
10186         if (r_refdef.scene.extraupdate)
10187                 S_ExtraUpdate ();
10188
10189         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
10190         {
10191                 R_DrawModelShadows();
10192                 R_ResetViewRendering3D();
10193                 // don't let sound skip if going slow
10194                 if (r_refdef.scene.extraupdate)
10195                         S_ExtraUpdate ();
10196         }
10197
10198         if (cl.csqc_vidvars.drawworld)
10199         {
10200                 if (cl_decals_newsystem.integer)
10201                 {
10202                         R_DrawModelDecals();
10203                         if (r_timereport_active)
10204                                 R_TimeReport("modeldecals");
10205                 }
10206                 else
10207                 {
10208                         R_DrawDecals();
10209                         if (r_timereport_active)
10210                                 R_TimeReport("decals");
10211                 }
10212
10213                 R_DrawParticles();
10214                 if (r_timereport_active)
10215                         R_TimeReport("particles");
10216
10217                 R_DrawExplosions();
10218                 if (r_timereport_active)
10219                         R_TimeReport("explosions");
10220
10221                 R_DrawLightningBeams();
10222                 if (r_timereport_active)
10223                         R_TimeReport("lightning");
10224         }
10225
10226         VM_CL_AddPolygonsToMeshQueue();
10227
10228         if (r_refdef.view.showdebug)
10229         {
10230                 if (cl_locs_show.integer)
10231                 {
10232                         R_DrawLocs();
10233                         if (r_timereport_active)
10234                                 R_TimeReport("showlocs");
10235                 }
10236
10237                 if (r_drawportals.integer)
10238                 {
10239                         R_DrawPortals();
10240                         if (r_timereport_active)
10241                                 R_TimeReport("portals");
10242                 }
10243
10244                 if (r_showbboxes.value > 0)
10245                 {
10246                         R_DrawEntityBBoxes();
10247                         if (r_timereport_active)
10248                                 R_TimeReport("bboxes");
10249                 }
10250         }
10251
10252         R_MeshQueue_RenderTransparent();
10253         if (r_timereport_active)
10254                 R_TimeReport("drawtrans");
10255
10256         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))
10257         {
10258                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
10259                 if (r_timereport_active)
10260                         R_TimeReport("worlddebug");
10261                 R_DrawModelsDebug();
10262                 if (r_timereport_active)
10263                         R_TimeReport("modeldebug");
10264         }
10265
10266         if (cl.csqc_vidvars.drawworld)
10267         {
10268                 R_Shadow_DrawCoronas();
10269                 if (r_timereport_active)
10270                         R_TimeReport("coronas");
10271         }
10272
10273 #if 0
10274         {
10275                 GL_DepthTest(false);
10276                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10277                 GL_Color(1, 1, 1, 1);
10278                 qglBegin(GL_POLYGON);
10279                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
10280                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
10281                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
10282                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
10283                 qglEnd();
10284                 qglBegin(GL_POLYGON);
10285                 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]);
10286                 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]);
10287                 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]);
10288                 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]);
10289                 qglEnd();
10290                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10291         }
10292 #endif
10293
10294         // don't let sound skip if going slow
10295         if (r_refdef.scene.extraupdate)
10296                 S_ExtraUpdate ();
10297
10298         R_ResetViewRendering2D();
10299 }
10300
10301 static const unsigned short bboxelements[36] =
10302 {
10303         5, 1, 3, 5, 3, 7,
10304         6, 2, 0, 6, 0, 4,
10305         7, 3, 2, 7, 2, 6,
10306         4, 0, 1, 4, 1, 5,
10307         4, 5, 7, 4, 7, 6,
10308         1, 0, 2, 1, 2, 3,
10309 };
10310
10311 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
10312 {
10313         int i;
10314         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
10315
10316         RSurf_ActiveWorldEntity();
10317
10318         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10319         GL_DepthMask(false);
10320         GL_DepthRange(0, 1);
10321         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10322 //      R_Mesh_ResetTextureState();
10323
10324         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
10325         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
10326         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
10327         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
10328         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
10329         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
10330         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
10331         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
10332         R_FillColors(color4f, 8, cr, cg, cb, ca);
10333         if (r_refdef.fogenabled)
10334         {
10335                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
10336                 {
10337                         f1 = RSurf_FogVertex(v);
10338                         f2 = 1 - f1;
10339                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10340                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10341                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10342                 }
10343         }
10344         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10345         R_Mesh_ResetTextureState();
10346         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10347         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10348 }
10349
10350 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10351 {
10352         int i;
10353         float color[4];
10354         prvm_edict_t *edict;
10355         prvm_prog_t *prog_save = prog;
10356
10357         // this function draws bounding boxes of server entities
10358         if (!sv.active)
10359                 return;
10360
10361         GL_CullFace(GL_NONE);
10362         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10363
10364         prog = 0;
10365         SV_VM_Begin();
10366         for (i = 0;i < numsurfaces;i++)
10367         {
10368                 edict = PRVM_EDICT_NUM(surfacelist[i]);
10369                 switch ((int)edict->fields.server->solid)
10370                 {
10371                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
10372                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
10373                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
10374                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10375                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
10376                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
10377                 }
10378                 color[3] *= r_showbboxes.value;
10379                 color[3] = bound(0, color[3], 1);
10380                 GL_DepthTest(!r_showdisabledepthtest.integer);
10381                 GL_CullFace(r_refdef.view.cullface_front);
10382                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10383         }
10384         SV_VM_End();
10385         prog = prog_save;
10386 }
10387
10388 static void R_DrawEntityBBoxes(void)
10389 {
10390         int i;
10391         prvm_edict_t *edict;
10392         vec3_t center;
10393         prvm_prog_t *prog_save = prog;
10394
10395         // this function draws bounding boxes of server entities
10396         if (!sv.active)
10397                 return;
10398
10399         prog = 0;
10400         SV_VM_Begin();
10401         for (i = 0;i < prog->num_edicts;i++)
10402         {
10403                 edict = PRVM_EDICT_NUM(i);
10404                 if (edict->priv.server->free)
10405                         continue;
10406                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10407                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10408                         continue;
10409                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10410                         continue;
10411                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10412                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10413         }
10414         SV_VM_End();
10415         prog = prog_save;
10416 }
10417
10418 static const int nomodelelement3i[24] =
10419 {
10420         5, 2, 0,
10421         5, 1, 2,
10422         5, 0, 3,
10423         5, 3, 1,
10424         0, 2, 4,
10425         2, 1, 4,
10426         3, 0, 4,
10427         1, 3, 4
10428 };
10429
10430 static const unsigned short nomodelelement3s[24] =
10431 {
10432         5, 2, 0,
10433         5, 1, 2,
10434         5, 0, 3,
10435         5, 3, 1,
10436         0, 2, 4,
10437         2, 1, 4,
10438         3, 0, 4,
10439         1, 3, 4
10440 };
10441
10442 static const float nomodelvertex3f[6*3] =
10443 {
10444         -16,   0,   0,
10445          16,   0,   0,
10446           0, -16,   0,
10447           0,  16,   0,
10448           0,   0, -16,
10449           0,   0,  16
10450 };
10451
10452 static const float nomodelcolor4f[6*4] =
10453 {
10454         0.0f, 0.0f, 0.5f, 1.0f,
10455         0.0f, 0.0f, 0.5f, 1.0f,
10456         0.0f, 0.5f, 0.0f, 1.0f,
10457         0.0f, 0.5f, 0.0f, 1.0f,
10458         0.5f, 0.0f, 0.0f, 1.0f,
10459         0.5f, 0.0f, 0.0f, 1.0f
10460 };
10461
10462 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10463 {
10464         int i;
10465         float f1, f2, *c;
10466         float color4f[6*4];
10467
10468         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);
10469
10470         // this is only called once per entity so numsurfaces is always 1, and
10471         // surfacelist is always {0}, so this code does not handle batches
10472
10473         if (rsurface.ent_flags & RENDER_ADDITIVE)
10474         {
10475                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10476                 GL_DepthMask(false);
10477         }
10478         else if (rsurface.colormod[3] < 1)
10479         {
10480                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10481                 GL_DepthMask(false);
10482         }
10483         else
10484         {
10485                 GL_BlendFunc(GL_ONE, GL_ZERO);
10486                 GL_DepthMask(true);
10487         }
10488         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10489         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10490         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10491         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10492         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10493         for (i = 0, c = color4f;i < 6;i++, c += 4)
10494         {
10495                 c[0] *= rsurface.colormod[0];
10496                 c[1] *= rsurface.colormod[1];
10497                 c[2] *= rsurface.colormod[2];
10498                 c[3] *= rsurface.colormod[3];
10499         }
10500         if (r_refdef.fogenabled)
10501         {
10502                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10503                 {
10504                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10505                         f2 = 1 - f1;
10506                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10507                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10508                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10509                 }
10510         }
10511 //      R_Mesh_ResetTextureState();
10512         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10513         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10514         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10515 }
10516
10517 void R_DrawNoModel(entity_render_t *ent)
10518 {
10519         vec3_t org;
10520         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10521         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10522                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10523         else
10524                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10525 }
10526
10527 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10528 {
10529         vec3_t right1, right2, diff, normal;
10530
10531         VectorSubtract (org2, org1, normal);
10532
10533         // calculate 'right' vector for start
10534         VectorSubtract (r_refdef.view.origin, org1, diff);
10535         CrossProduct (normal, diff, right1);
10536         VectorNormalize (right1);
10537
10538         // calculate 'right' vector for end
10539         VectorSubtract (r_refdef.view.origin, org2, diff);
10540         CrossProduct (normal, diff, right2);
10541         VectorNormalize (right2);
10542
10543         vert[ 0] = org1[0] + width * right1[0];
10544         vert[ 1] = org1[1] + width * right1[1];
10545         vert[ 2] = org1[2] + width * right1[2];
10546         vert[ 3] = org1[0] - width * right1[0];
10547         vert[ 4] = org1[1] - width * right1[1];
10548         vert[ 5] = org1[2] - width * right1[2];
10549         vert[ 6] = org2[0] - width * right2[0];
10550         vert[ 7] = org2[1] - width * right2[1];
10551         vert[ 8] = org2[2] - width * right2[2];
10552         vert[ 9] = org2[0] + width * right2[0];
10553         vert[10] = org2[1] + width * right2[1];
10554         vert[11] = org2[2] + width * right2[2];
10555 }
10556
10557 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)
10558 {
10559         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10560         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10561         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10562         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10563         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10564         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10565         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10566         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10567         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10568         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10569         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10570         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10571 }
10572
10573 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10574 {
10575         int i;
10576         float *vertex3f;
10577         float v[3];
10578         VectorSet(v, x, y, z);
10579         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10580                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10581                         break;
10582         if (i == mesh->numvertices)
10583         {
10584                 if (mesh->numvertices < mesh->maxvertices)
10585                 {
10586                         VectorCopy(v, vertex3f);
10587                         mesh->numvertices++;
10588                 }
10589                 return mesh->numvertices;
10590         }
10591         else
10592                 return i;
10593 }
10594
10595 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10596 {
10597         int i;
10598         int *e, element[3];
10599         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10600         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10601         e = mesh->element3i + mesh->numtriangles * 3;
10602         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10603         {
10604                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10605                 if (mesh->numtriangles < mesh->maxtriangles)
10606                 {
10607                         *e++ = element[0];
10608                         *e++ = element[1];
10609                         *e++ = element[2];
10610                         mesh->numtriangles++;
10611                 }
10612                 element[1] = element[2];
10613         }
10614 }
10615
10616 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10617 {
10618         int i;
10619         int *e, element[3];
10620         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10621         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10622         e = mesh->element3i + mesh->numtriangles * 3;
10623         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10624         {
10625                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10626                 if (mesh->numtriangles < mesh->maxtriangles)
10627                 {
10628                         *e++ = element[0];
10629                         *e++ = element[1];
10630                         *e++ = element[2];
10631                         mesh->numtriangles++;
10632                 }
10633                 element[1] = element[2];
10634         }
10635 }
10636
10637 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10638 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10639 {
10640         int planenum, planenum2;
10641         int w;
10642         int tempnumpoints;
10643         mplane_t *plane, *plane2;
10644         double maxdist;
10645         double temppoints[2][256*3];
10646         // figure out how large a bounding box we need to properly compute this brush
10647         maxdist = 0;
10648         for (w = 0;w < numplanes;w++)
10649                 maxdist = max(maxdist, fabs(planes[w].dist));
10650         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10651         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10652         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10653         {
10654                 w = 0;
10655                 tempnumpoints = 4;
10656                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10657                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10658                 {
10659                         if (planenum2 == planenum)
10660                                 continue;
10661                         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);
10662                         w = !w;
10663                 }
10664                 if (tempnumpoints < 3)
10665                         continue;
10666                 // generate elements forming a triangle fan for this polygon
10667                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10668         }
10669 }
10670
10671 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)
10672 {
10673         texturelayer_t *layer;
10674         layer = t->currentlayers + t->currentnumlayers++;
10675         layer->type = type;
10676         layer->depthmask = depthmask;
10677         layer->blendfunc1 = blendfunc1;
10678         layer->blendfunc2 = blendfunc2;
10679         layer->texture = texture;
10680         layer->texmatrix = *matrix;
10681         layer->color[0] = r;
10682         layer->color[1] = g;
10683         layer->color[2] = b;
10684         layer->color[3] = a;
10685 }
10686
10687 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10688 {
10689         if(parms[0] == 0 && parms[1] == 0)
10690                 return false;
10691         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10692                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10693                         return false;
10694         return true;
10695 }
10696
10697 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10698 {
10699         double index, f;
10700         index = parms[2] + r_refdef.scene.time * parms[3];
10701         index -= floor(index);
10702         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10703         {
10704         default:
10705         case Q3WAVEFUNC_NONE:
10706         case Q3WAVEFUNC_NOISE:
10707         case Q3WAVEFUNC_COUNT:
10708                 f = 0;
10709                 break;
10710         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10711         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10712         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10713         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10714         case Q3WAVEFUNC_TRIANGLE:
10715                 index *= 4;
10716                 f = index - floor(index);
10717                 if (index < 1)
10718                         f = f;
10719                 else if (index < 2)
10720                         f = 1 - f;
10721                 else if (index < 3)
10722                         f = -f;
10723                 else
10724                         f = -(1 - f);
10725                 break;
10726         }
10727         f = parms[0] + parms[1] * f;
10728         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10729                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10730         return (float) f;
10731 }
10732
10733 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10734 {
10735         int w, h, idx;
10736         float f;
10737         float tcmat[12];
10738         matrix4x4_t matrix, temp;
10739         switch(tcmod->tcmod)
10740         {
10741                 case Q3TCMOD_COUNT:
10742                 case Q3TCMOD_NONE:
10743                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10744                                 matrix = r_waterscrollmatrix;
10745                         else
10746                                 matrix = identitymatrix;
10747                         break;
10748                 case Q3TCMOD_ENTITYTRANSLATE:
10749                         // this is used in Q3 to allow the gamecode to control texcoord
10750                         // scrolling on the entity, which is not supported in darkplaces yet.
10751                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10752                         break;
10753                 case Q3TCMOD_ROTATE:
10754                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10755                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10756                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10757                         break;
10758                 case Q3TCMOD_SCALE:
10759                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10760                         break;
10761                 case Q3TCMOD_SCROLL:
10762                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10763                         break;
10764                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10765                         w = (int) tcmod->parms[0];
10766                         h = (int) tcmod->parms[1];
10767                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10768                         f = f - floor(f);
10769                         idx = (int) floor(f * w * h);
10770                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10771                         break;
10772                 case Q3TCMOD_STRETCH:
10773                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10774                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10775                         break;
10776                 case Q3TCMOD_TRANSFORM:
10777                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10778                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10779                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10780                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10781                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10782                         break;
10783                 case Q3TCMOD_TURBULENT:
10784                         // this is handled in the RSurf_PrepareVertices function
10785                         matrix = identitymatrix;
10786                         break;
10787         }
10788         temp = *texmatrix;
10789         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10790 }
10791
10792 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10793 {
10794         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10795         char name[MAX_QPATH];
10796         skinframe_t *skinframe;
10797         unsigned char pixels[296*194];
10798         strlcpy(cache->name, skinname, sizeof(cache->name));
10799         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10800         if (developer_loading.integer)
10801                 Con_Printf("loading %s\n", name);
10802         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10803         if (!skinframe || !skinframe->base)
10804         {
10805                 unsigned char *f;
10806                 fs_offset_t filesize;
10807                 skinframe = NULL;
10808                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10809                 if (f)
10810                 {
10811                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10812                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10813                         Mem_Free(f);
10814                 }
10815         }
10816         cache->skinframe = skinframe;
10817 }
10818
10819 texture_t *R_GetCurrentTexture(texture_t *t)
10820 {
10821         int i;
10822         const entity_render_t *ent = rsurface.entity;
10823         dp_model_t *model = ent->model;
10824         q3shaderinfo_layer_tcmod_t *tcmod;
10825
10826         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10827                 return t->currentframe;
10828         t->update_lastrenderframe = r_textureframe;
10829         t->update_lastrenderentity = (void *)ent;
10830
10831         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10832                 t->camera_entity = ent->entitynumber;
10833         else
10834                 t->camera_entity = 0;
10835
10836         // switch to an alternate material if this is a q1bsp animated material
10837         {
10838                 texture_t *texture = t;
10839                 int s = rsurface.ent_skinnum;
10840                 if ((unsigned int)s >= (unsigned int)model->numskins)
10841                         s = 0;
10842                 if (model->skinscenes)
10843                 {
10844                         if (model->skinscenes[s].framecount > 1)
10845                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10846                         else
10847                                 s = model->skinscenes[s].firstframe;
10848                 }
10849                 if (s > 0)
10850                         t = t + s * model->num_surfaces;
10851                 if (t->animated)
10852                 {
10853                         // use an alternate animation if the entity's frame is not 0,
10854                         // and only if the texture has an alternate animation
10855                         if (rsurface.ent_alttextures && t->anim_total[1])
10856                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10857                         else
10858                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10859                 }
10860                 texture->currentframe = t;
10861         }
10862
10863         // update currentskinframe to be a qw skin or animation frame
10864         if (rsurface.ent_qwskin >= 0)
10865         {
10866                 i = rsurface.ent_qwskin;
10867                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10868                 {
10869                         r_qwskincache_size = cl.maxclients;
10870                         if (r_qwskincache)
10871                                 Mem_Free(r_qwskincache);
10872                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10873                 }
10874                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10875                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10876                 t->currentskinframe = r_qwskincache[i].skinframe;
10877                 if (t->currentskinframe == NULL)
10878                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10879         }
10880         else if (t->numskinframes >= 2)
10881                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10882         if (t->backgroundnumskinframes >= 2)
10883                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10884
10885         t->currentmaterialflags = t->basematerialflags;
10886         t->currentalpha = rsurface.colormod[3];
10887         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10888                 t->currentalpha *= r_wateralpha.value;
10889         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10890                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10891         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10892                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10893         if (!(rsurface.ent_flags & RENDER_LIGHT))
10894                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10895         else if (FAKELIGHT_ENABLED)
10896         {
10897                         // no modellight if using fakelight for the map
10898         }
10899         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10900         {
10901                 // pick a model lighting mode
10902                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10903                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10904                 else
10905                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10906         }
10907         if (rsurface.ent_flags & RENDER_ADDITIVE)
10908                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10909         else if (t->currentalpha < 1)
10910                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10911         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10912                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10913         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10914                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10915         if (t->backgroundnumskinframes)
10916                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10917         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10918         {
10919                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10920                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10921         }
10922         else
10923                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10924         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10925                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10926
10927         // there is no tcmod
10928         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10929         {
10930                 t->currenttexmatrix = r_waterscrollmatrix;
10931                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10932         }
10933         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10934         {
10935                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10936                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10937         }
10938
10939         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10940                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10941         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10942                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10943
10944         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10945         if (t->currentskinframe->qpixels)
10946                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10947         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10948         if (!t->basetexture)
10949                 t->basetexture = r_texture_notexture;
10950         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10951         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10952         t->nmaptexture = t->currentskinframe->nmap;
10953         if (!t->nmaptexture)
10954                 t->nmaptexture = r_texture_blanknormalmap;
10955         t->glosstexture = r_texture_black;
10956         t->glowtexture = t->currentskinframe->glow;
10957         t->fogtexture = t->currentskinframe->fog;
10958         t->reflectmasktexture = t->currentskinframe->reflect;
10959         if (t->backgroundnumskinframes)
10960         {
10961                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10962                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10963                 t->backgroundglosstexture = r_texture_black;
10964                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10965                 if (!t->backgroundnmaptexture)
10966                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10967         }
10968         else
10969         {
10970                 t->backgroundbasetexture = r_texture_white;
10971                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10972                 t->backgroundglosstexture = r_texture_black;
10973                 t->backgroundglowtexture = NULL;
10974         }
10975         t->specularpower = r_shadow_glossexponent.value;
10976         // TODO: store reference values for these in the texture?
10977         t->specularscale = 0;
10978         if (r_shadow_gloss.integer > 0)
10979         {
10980                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10981                 {
10982                         if (r_shadow_glossintensity.value > 0)
10983                         {
10984                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10985                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10986                                 t->specularscale = r_shadow_glossintensity.value;
10987                         }
10988                 }
10989                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10990                 {
10991                         t->glosstexture = r_texture_white;
10992                         t->backgroundglosstexture = r_texture_white;
10993                         t->specularscale = r_shadow_gloss2intensity.value;
10994                         t->specularpower = r_shadow_gloss2exponent.value;
10995                 }
10996         }
10997         t->specularscale *= t->specularscalemod;
10998         t->specularpower *= t->specularpowermod;
10999
11000         // lightmaps mode looks bad with dlights using actual texturing, so turn
11001         // off the colormap and glossmap, but leave the normalmap on as it still
11002         // accurately represents the shading involved
11003         if (gl_lightmaps.integer)
11004         {
11005                 t->basetexture = r_texture_grey128;
11006                 t->pantstexture = r_texture_black;
11007                 t->shirttexture = r_texture_black;
11008                 t->nmaptexture = r_texture_blanknormalmap;
11009                 t->glosstexture = r_texture_black;
11010                 t->glowtexture = NULL;
11011                 t->fogtexture = NULL;
11012                 t->reflectmasktexture = NULL;
11013                 t->backgroundbasetexture = NULL;
11014                 t->backgroundnmaptexture = r_texture_blanknormalmap;
11015                 t->backgroundglosstexture = r_texture_black;
11016                 t->backgroundglowtexture = NULL;
11017                 t->specularscale = 0;
11018                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
11019         }
11020
11021         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
11022         VectorClear(t->dlightcolor);
11023         t->currentnumlayers = 0;
11024         if (t->currentmaterialflags & MATERIALFLAG_WALL)
11025         {
11026                 int blendfunc1, blendfunc2;
11027                 qboolean depthmask;
11028                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
11029                 {
11030                         blendfunc1 = GL_SRC_ALPHA;
11031                         blendfunc2 = GL_ONE;
11032                 }
11033                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
11034                 {
11035                         blendfunc1 = GL_SRC_ALPHA;
11036                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
11037                 }
11038                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11039                 {
11040                         blendfunc1 = t->customblendfunc[0];
11041                         blendfunc2 = t->customblendfunc[1];
11042                 }
11043                 else
11044                 {
11045                         blendfunc1 = GL_ONE;
11046                         blendfunc2 = GL_ZERO;
11047                 }
11048                 // don't colormod evilblend textures
11049                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
11050                         VectorSet(t->lightmapcolor, 1, 1, 1);
11051                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
11052                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11053                 {
11054                         // fullbright is not affected by r_refdef.lightmapintensity
11055                         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]);
11056                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
11057                                 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]);
11058                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
11059                                 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]);
11060                 }
11061                 else
11062                 {
11063                         vec3_t ambientcolor;
11064                         float colorscale;
11065                         // set the color tint used for lights affecting this surface
11066                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
11067                         colorscale = 2;
11068                         // q3bsp has no lightmap updates, so the lightstylevalue that
11069                         // would normally be baked into the lightmap must be
11070                         // applied to the color
11071                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
11072                         if (model->type == mod_brushq3)
11073                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
11074                         colorscale *= r_refdef.lightmapintensity;
11075                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
11076                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
11077                         // basic lit geometry
11078                         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]);
11079                         // add pants/shirt if needed
11080                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
11081                                 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]);
11082                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
11083                                 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]);
11084                         // now add ambient passes if needed
11085                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
11086                         {
11087                                 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]);
11088                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
11089                                         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]);
11090                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
11091                                         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]);
11092                         }
11093                 }
11094                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
11095                         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]);
11096                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
11097                 {
11098                         // if this is opaque use alpha blend which will darken the earlier
11099                         // passes cheaply.
11100                         //
11101                         // if this is an alpha blended material, all the earlier passes
11102                         // were darkened by fog already, so we only need to add the fog
11103                         // color ontop through the fog mask texture
11104                         //
11105                         // if this is an additive blended material, all the earlier passes
11106                         // were darkened by fog already, and we should not add fog color
11107                         // (because the background was not darkened, there is no fog color
11108                         // that was lost behind it).
11109                         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]);
11110                 }
11111         }
11112
11113         return t->currentframe;
11114 }
11115
11116 rsurfacestate_t rsurface;
11117
11118 void RSurf_ActiveWorldEntity(void)
11119 {
11120         dp_model_t *model = r_refdef.scene.worldmodel;
11121         //if (rsurface.entity == r_refdef.scene.worldentity)
11122         //      return;
11123         rsurface.entity = r_refdef.scene.worldentity;
11124         rsurface.skeleton = NULL;
11125         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
11126         rsurface.ent_skinnum = 0;
11127         rsurface.ent_qwskin = -1;
11128         rsurface.ent_shadertime = 0;
11129         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
11130         rsurface.matrix = identitymatrix;
11131         rsurface.inversematrix = identitymatrix;
11132         rsurface.matrixscale = 1;
11133         rsurface.inversematrixscale = 1;
11134         R_EntityMatrix(&identitymatrix);
11135         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
11136         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
11137         rsurface.fograngerecip = r_refdef.fograngerecip;
11138         rsurface.fogheightfade = r_refdef.fogheightfade;
11139         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
11140         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11141         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11142         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11143         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11144         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11145         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11146         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
11147         rsurface.colormod[3] = 1;
11148         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);
11149         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11150         rsurface.frameblend[0].lerp = 1;
11151         rsurface.ent_alttextures = false;
11152         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11153         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11154         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11155         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11156         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11157         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11158         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11159         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11160         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11161         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11162         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11163         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11164         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11165         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11166         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11167         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11168         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11169         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11170         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11171         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11172         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11173         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11174         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11175         rsurface.modelelement3i = model->surfmesh.data_element3i;
11176         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11177         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11178         rsurface.modelelement3s = model->surfmesh.data_element3s;
11179         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11180         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11181         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11182         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11183         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11184         rsurface.modelsurfaces = model->data_surfaces;
11185         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11186         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11187         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
11188         rsurface.modelgeneratedvertex = false;
11189         rsurface.batchgeneratedvertex = false;
11190         rsurface.batchfirstvertex = 0;
11191         rsurface.batchnumvertices = 0;
11192         rsurface.batchfirsttriangle = 0;
11193         rsurface.batchnumtriangles = 0;
11194         rsurface.batchvertex3f  = NULL;
11195         rsurface.batchvertex3f_vertexbuffer = NULL;
11196         rsurface.batchvertex3f_bufferoffset = 0;
11197         rsurface.batchsvector3f = NULL;
11198         rsurface.batchsvector3f_vertexbuffer = NULL;
11199         rsurface.batchsvector3f_bufferoffset = 0;
11200         rsurface.batchtvector3f = NULL;
11201         rsurface.batchtvector3f_vertexbuffer = NULL;
11202         rsurface.batchtvector3f_bufferoffset = 0;
11203         rsurface.batchnormal3f  = NULL;
11204         rsurface.batchnormal3f_vertexbuffer = NULL;
11205         rsurface.batchnormal3f_bufferoffset = 0;
11206         rsurface.batchlightmapcolor4f = NULL;
11207         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11208         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11209         rsurface.batchtexcoordtexture2f = NULL;
11210         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11211         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11212         rsurface.batchtexcoordlightmap2f = NULL;
11213         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11214         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11215         rsurface.batchvertexmesh = NULL;
11216         rsurface.batchvertexmeshbuffer = NULL;
11217         rsurface.batchvertex3fbuffer = NULL;
11218         rsurface.batchelement3i = NULL;
11219         rsurface.batchelement3i_indexbuffer = NULL;
11220         rsurface.batchelement3i_bufferoffset = 0;
11221         rsurface.batchelement3s = NULL;
11222         rsurface.batchelement3s_indexbuffer = NULL;
11223         rsurface.batchelement3s_bufferoffset = 0;
11224         rsurface.passcolor4f = NULL;
11225         rsurface.passcolor4f_vertexbuffer = NULL;
11226         rsurface.passcolor4f_bufferoffset = 0;
11227 }
11228
11229 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
11230 {
11231         dp_model_t *model = ent->model;
11232         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
11233         //      return;
11234         rsurface.entity = (entity_render_t *)ent;
11235         rsurface.skeleton = ent->skeleton;
11236         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
11237         rsurface.ent_skinnum = ent->skinnum;
11238         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;
11239         rsurface.ent_shadertime = ent->shadertime;
11240         rsurface.ent_flags = ent->flags;
11241         rsurface.matrix = ent->matrix;
11242         rsurface.inversematrix = ent->inversematrix;
11243         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11244         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11245         R_EntityMatrix(&rsurface.matrix);
11246         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11247         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11248         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11249         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11250         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11251         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11252         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
11253         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
11254         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
11255         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
11256         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
11257         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
11258         rsurface.colormod[3] = ent->alpha;
11259         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
11260         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
11261         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
11262         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11263         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11264         if (ent->model->brush.submodel && !prepass)
11265         {
11266                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
11267                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
11268         }
11269         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
11270         {
11271                 if (ent->animcache_vertex3f)
11272                 {
11273                         rsurface.modelvertex3f = ent->animcache_vertex3f;
11274                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
11275                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
11276                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
11277                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
11278                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
11279                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
11280                 }
11281                 else if (wanttangents)
11282                 {
11283                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11284                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11285                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11286                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11287                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
11288                         rsurface.modelvertexmesh = NULL;
11289                         rsurface.modelvertexmeshbuffer = NULL;
11290                         rsurface.modelvertex3fbuffer = NULL;
11291                 }
11292                 else if (wantnormals)
11293                 {
11294                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11295                         rsurface.modelsvector3f = NULL;
11296                         rsurface.modeltvector3f = NULL;
11297                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11298                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
11299                         rsurface.modelvertexmesh = NULL;
11300                         rsurface.modelvertexmeshbuffer = NULL;
11301                         rsurface.modelvertex3fbuffer = NULL;
11302                 }
11303                 else
11304                 {
11305                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11306                         rsurface.modelsvector3f = NULL;
11307                         rsurface.modeltvector3f = NULL;
11308                         rsurface.modelnormal3f = NULL;
11309                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
11310                         rsurface.modelvertexmesh = NULL;
11311                         rsurface.modelvertexmeshbuffer = NULL;
11312                         rsurface.modelvertex3fbuffer = NULL;
11313                 }
11314                 rsurface.modelvertex3f_vertexbuffer = 0;
11315                 rsurface.modelvertex3f_bufferoffset = 0;
11316                 rsurface.modelsvector3f_vertexbuffer = 0;
11317                 rsurface.modelsvector3f_bufferoffset = 0;
11318                 rsurface.modeltvector3f_vertexbuffer = 0;
11319                 rsurface.modeltvector3f_bufferoffset = 0;
11320                 rsurface.modelnormal3f_vertexbuffer = 0;
11321                 rsurface.modelnormal3f_bufferoffset = 0;
11322                 rsurface.modelgeneratedvertex = true;
11323         }
11324         else
11325         {
11326                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11327                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11328                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11329                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11330                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11331                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11332                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11333                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11334                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11335                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11336                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11337                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11338                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11339                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11340                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
11341                 rsurface.modelgeneratedvertex = false;
11342         }
11343         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11344         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11345         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11346         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11347         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11348         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11349         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11350         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11351         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11352         rsurface.modelelement3i = model->surfmesh.data_element3i;
11353         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11354         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11355         rsurface.modelelement3s = model->surfmesh.data_element3s;
11356         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11357         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11358         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11359         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11360         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11361         rsurface.modelsurfaces = model->data_surfaces;
11362         rsurface.batchgeneratedvertex = false;
11363         rsurface.batchfirstvertex = 0;
11364         rsurface.batchnumvertices = 0;
11365         rsurface.batchfirsttriangle = 0;
11366         rsurface.batchnumtriangles = 0;
11367         rsurface.batchvertex3f  = NULL;
11368         rsurface.batchvertex3f_vertexbuffer = NULL;
11369         rsurface.batchvertex3f_bufferoffset = 0;
11370         rsurface.batchsvector3f = NULL;
11371         rsurface.batchsvector3f_vertexbuffer = NULL;
11372         rsurface.batchsvector3f_bufferoffset = 0;
11373         rsurface.batchtvector3f = NULL;
11374         rsurface.batchtvector3f_vertexbuffer = NULL;
11375         rsurface.batchtvector3f_bufferoffset = 0;
11376         rsurface.batchnormal3f  = NULL;
11377         rsurface.batchnormal3f_vertexbuffer = NULL;
11378         rsurface.batchnormal3f_bufferoffset = 0;
11379         rsurface.batchlightmapcolor4f = NULL;
11380         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11381         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11382         rsurface.batchtexcoordtexture2f = NULL;
11383         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11384         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11385         rsurface.batchtexcoordlightmap2f = NULL;
11386         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11387         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11388         rsurface.batchvertexmesh = NULL;
11389         rsurface.batchvertexmeshbuffer = NULL;
11390         rsurface.batchvertex3fbuffer = NULL;
11391         rsurface.batchelement3i = NULL;
11392         rsurface.batchelement3i_indexbuffer = NULL;
11393         rsurface.batchelement3i_bufferoffset = 0;
11394         rsurface.batchelement3s = NULL;
11395         rsurface.batchelement3s_indexbuffer = NULL;
11396         rsurface.batchelement3s_bufferoffset = 0;
11397         rsurface.passcolor4f = NULL;
11398         rsurface.passcolor4f_vertexbuffer = NULL;
11399         rsurface.passcolor4f_bufferoffset = 0;
11400 }
11401
11402 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)
11403 {
11404         rsurface.entity = r_refdef.scene.worldentity;
11405         rsurface.skeleton = NULL;
11406         rsurface.ent_skinnum = 0;
11407         rsurface.ent_qwskin = -1;
11408         rsurface.ent_shadertime = shadertime;
11409         rsurface.ent_flags = entflags;
11410         rsurface.modelnumvertices = numvertices;
11411         rsurface.modelnumtriangles = numtriangles;
11412         rsurface.matrix = *matrix;
11413         rsurface.inversematrix = *inversematrix;
11414         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11415         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11416         R_EntityMatrix(&rsurface.matrix);
11417         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11418         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11419         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11420         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11421         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11422         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11423         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11424         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11425         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11426         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11427         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11428         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11429         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);
11430         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11431         rsurface.frameblend[0].lerp = 1;
11432         rsurface.ent_alttextures = false;
11433         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11434         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11435         if (wanttangents)
11436         {
11437                 rsurface.modelvertex3f = (float *)vertex3f;
11438                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11439                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11440                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11441         }
11442         else if (wantnormals)
11443         {
11444                 rsurface.modelvertex3f = (float *)vertex3f;
11445                 rsurface.modelsvector3f = NULL;
11446                 rsurface.modeltvector3f = NULL;
11447                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11448         }
11449         else
11450         {
11451                 rsurface.modelvertex3f = (float *)vertex3f;
11452                 rsurface.modelsvector3f = NULL;
11453                 rsurface.modeltvector3f = NULL;
11454                 rsurface.modelnormal3f = NULL;
11455         }
11456         rsurface.modelvertexmesh = NULL;
11457         rsurface.modelvertexmeshbuffer = NULL;
11458         rsurface.modelvertex3fbuffer = NULL;
11459         rsurface.modelvertex3f_vertexbuffer = 0;
11460         rsurface.modelvertex3f_bufferoffset = 0;
11461         rsurface.modelsvector3f_vertexbuffer = 0;
11462         rsurface.modelsvector3f_bufferoffset = 0;
11463         rsurface.modeltvector3f_vertexbuffer = 0;
11464         rsurface.modeltvector3f_bufferoffset = 0;
11465         rsurface.modelnormal3f_vertexbuffer = 0;
11466         rsurface.modelnormal3f_bufferoffset = 0;
11467         rsurface.modelgeneratedvertex = true;
11468         rsurface.modellightmapcolor4f  = (float *)color4f;
11469         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11470         rsurface.modellightmapcolor4f_bufferoffset = 0;
11471         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
11472         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11473         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11474         rsurface.modeltexcoordlightmap2f  = NULL;
11475         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11476         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11477         rsurface.modelelement3i = (int *)element3i;
11478         rsurface.modelelement3i_indexbuffer = NULL;
11479         rsurface.modelelement3i_bufferoffset = 0;
11480         rsurface.modelelement3s = (unsigned short *)element3s;
11481         rsurface.modelelement3s_indexbuffer = NULL;
11482         rsurface.modelelement3s_bufferoffset = 0;
11483         rsurface.modellightmapoffsets = NULL;
11484         rsurface.modelsurfaces = NULL;
11485         rsurface.batchgeneratedvertex = false;
11486         rsurface.batchfirstvertex = 0;
11487         rsurface.batchnumvertices = 0;
11488         rsurface.batchfirsttriangle = 0;
11489         rsurface.batchnumtriangles = 0;
11490         rsurface.batchvertex3f  = NULL;
11491         rsurface.batchvertex3f_vertexbuffer = NULL;
11492         rsurface.batchvertex3f_bufferoffset = 0;
11493         rsurface.batchsvector3f = NULL;
11494         rsurface.batchsvector3f_vertexbuffer = NULL;
11495         rsurface.batchsvector3f_bufferoffset = 0;
11496         rsurface.batchtvector3f = NULL;
11497         rsurface.batchtvector3f_vertexbuffer = NULL;
11498         rsurface.batchtvector3f_bufferoffset = 0;
11499         rsurface.batchnormal3f  = NULL;
11500         rsurface.batchnormal3f_vertexbuffer = NULL;
11501         rsurface.batchnormal3f_bufferoffset = 0;
11502         rsurface.batchlightmapcolor4f = NULL;
11503         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11504         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11505         rsurface.batchtexcoordtexture2f = NULL;
11506         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11507         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11508         rsurface.batchtexcoordlightmap2f = NULL;
11509         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11510         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11511         rsurface.batchvertexmesh = NULL;
11512         rsurface.batchvertexmeshbuffer = NULL;
11513         rsurface.batchvertex3fbuffer = NULL;
11514         rsurface.batchelement3i = NULL;
11515         rsurface.batchelement3i_indexbuffer = NULL;
11516         rsurface.batchelement3i_bufferoffset = 0;
11517         rsurface.batchelement3s = NULL;
11518         rsurface.batchelement3s_indexbuffer = NULL;
11519         rsurface.batchelement3s_bufferoffset = 0;
11520         rsurface.passcolor4f = NULL;
11521         rsurface.passcolor4f_vertexbuffer = NULL;
11522         rsurface.passcolor4f_bufferoffset = 0;
11523
11524         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11525         {
11526                 if ((wantnormals || wanttangents) && !normal3f)
11527                 {
11528                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11529                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11530                 }
11531                 if (wanttangents && !svector3f)
11532                 {
11533                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11534                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11535                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
11536                 }
11537         }
11538 }
11539
11540 float RSurf_FogPoint(const float *v)
11541 {
11542         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11543         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11544         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11545         float FogHeightFade = r_refdef.fogheightfade;
11546         float fogfrac;
11547         unsigned int fogmasktableindex;
11548         if (r_refdef.fogplaneviewabove)
11549                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11550         else
11551                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11552         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11553         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11554 }
11555
11556 float RSurf_FogVertex(const float *v)
11557 {
11558         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11559         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11560         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11561         float FogHeightFade = rsurface.fogheightfade;
11562         float fogfrac;
11563         unsigned int fogmasktableindex;
11564         if (r_refdef.fogplaneviewabove)
11565                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11566         else
11567                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11568         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11569         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11570 }
11571
11572 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11573 {
11574         int i;
11575         for (i = 0;i < numelements;i++)
11576                 outelement3i[i] = inelement3i[i] + adjust;
11577 }
11578
11579 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11580 extern cvar_t gl_vbo;
11581 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11582 {
11583         int deformindex;
11584         int firsttriangle;
11585         int numtriangles;
11586         int firstvertex;
11587         int endvertex;
11588         int numvertices;
11589         int surfacefirsttriangle;
11590         int surfacenumtriangles;
11591         int surfacefirstvertex;
11592         int surfaceendvertex;
11593         int surfacenumvertices;
11594         int batchnumvertices;
11595         int batchnumtriangles;
11596         int needsupdate;
11597         int i, j;
11598         qboolean gaps;
11599         qboolean dynamicvertex;
11600         float amplitude;
11601         float animpos;
11602         float scale;
11603         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11604         float waveparms[4];
11605         q3shaderinfo_deform_t *deform;
11606         const msurface_t *surface, *firstsurface;
11607         r_vertexmesh_t *vertexmesh;
11608         if (!texturenumsurfaces)
11609                 return;
11610         // find vertex range of this surface batch
11611         gaps = false;
11612         firstsurface = texturesurfacelist[0];
11613         firsttriangle = firstsurface->num_firsttriangle;
11614         batchnumvertices = 0;
11615         batchnumtriangles = 0;
11616         firstvertex = endvertex = firstsurface->num_firstvertex;
11617         for (i = 0;i < texturenumsurfaces;i++)
11618         {
11619                 surface = texturesurfacelist[i];
11620                 if (surface != firstsurface + i)
11621                         gaps = true;
11622                 surfacefirstvertex = surface->num_firstvertex;
11623                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11624                 surfacenumvertices = surface->num_vertices;
11625                 surfacenumtriangles = surface->num_triangles;
11626                 if (firstvertex > surfacefirstvertex)
11627                         firstvertex = surfacefirstvertex;
11628                 if (endvertex < surfaceendvertex)
11629                         endvertex = surfaceendvertex;
11630                 batchnumvertices += surfacenumvertices;
11631                 batchnumtriangles += surfacenumtriangles;
11632         }
11633
11634         // we now know the vertex range used, and if there are any gaps in it
11635         rsurface.batchfirstvertex = firstvertex;
11636         rsurface.batchnumvertices = endvertex - firstvertex;
11637         rsurface.batchfirsttriangle = firsttriangle;
11638         rsurface.batchnumtriangles = batchnumtriangles;
11639
11640         // this variable holds flags for which properties have been updated that
11641         // may require regenerating vertexmesh array...
11642         needsupdate = 0;
11643
11644         // check if any dynamic vertex processing must occur
11645         dynamicvertex = false;
11646
11647         // if there is a chance of animated vertex colors, it's a dynamic batch
11648         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11649         {
11650                 dynamicvertex = true;
11651                 batchneed |= BATCHNEED_NOGAPS;
11652                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
11653         }
11654
11655         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11656         {
11657                 switch (deform->deform)
11658                 {
11659                 default:
11660                 case Q3DEFORM_PROJECTIONSHADOW:
11661                 case Q3DEFORM_TEXT0:
11662                 case Q3DEFORM_TEXT1:
11663                 case Q3DEFORM_TEXT2:
11664                 case Q3DEFORM_TEXT3:
11665                 case Q3DEFORM_TEXT4:
11666                 case Q3DEFORM_TEXT5:
11667                 case Q3DEFORM_TEXT6:
11668                 case Q3DEFORM_TEXT7:
11669                 case Q3DEFORM_NONE:
11670                         break;
11671                 case Q3DEFORM_AUTOSPRITE:
11672                         dynamicvertex = true;
11673                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11674                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11675                         break;
11676                 case Q3DEFORM_AUTOSPRITE2:
11677                         dynamicvertex = true;
11678                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11679                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11680                         break;
11681                 case Q3DEFORM_NORMAL:
11682                         dynamicvertex = true;
11683                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11684                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11685                         break;
11686                 case Q3DEFORM_WAVE:
11687                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11688                                 break; // if wavefunc is a nop, ignore this transform
11689                         dynamicvertex = true;
11690                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11691                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11692                         break;
11693                 case Q3DEFORM_BULGE:
11694                         dynamicvertex = true;
11695                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11696                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11697                         break;
11698                 case Q3DEFORM_MOVE:
11699                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11700                                 break; // if wavefunc is a nop, ignore this transform
11701                         dynamicvertex = true;
11702                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11703                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
11704                         break;
11705                 }
11706         }
11707         switch(rsurface.texture->tcgen.tcgen)
11708         {
11709         default:
11710         case Q3TCGEN_TEXTURE:
11711                 break;
11712         case Q3TCGEN_LIGHTMAP:
11713                 dynamicvertex = true;
11714                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11715                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11716                 break;
11717         case Q3TCGEN_VECTOR:
11718                 dynamicvertex = true;
11719                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11720                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11721                 break;
11722         case Q3TCGEN_ENVIRONMENT:
11723                 dynamicvertex = true;
11724                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11725                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11726                 break;
11727         }
11728         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11729         {
11730                 dynamicvertex = true;
11731                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11732                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11733         }
11734
11735         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11736         {
11737                 dynamicvertex = true;
11738                 batchneed |= BATCHNEED_NOGAPS;
11739                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11740         }
11741
11742         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11743         {
11744                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11745                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11746                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11747                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11748                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11749                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11750                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11751         }
11752
11753         // when the model data has no vertex buffer (dynamic mesh), we need to
11754         // eliminate gaps
11755         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
11756                 batchneed |= BATCHNEED_NOGAPS;
11757
11758         // if needsupdate, we have to do a dynamic vertex batch for sure
11759         if (needsupdate & batchneed)
11760                 dynamicvertex = true;
11761
11762         // see if we need to build vertexmesh from arrays
11763         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11764                 dynamicvertex = true;
11765
11766         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11767         // also some drivers strongly dislike firstvertex
11768         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11769                 dynamicvertex = true;
11770
11771         rsurface.batchvertex3f = rsurface.modelvertex3f;
11772         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11773         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11774         rsurface.batchsvector3f = rsurface.modelsvector3f;
11775         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11776         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11777         rsurface.batchtvector3f = rsurface.modeltvector3f;
11778         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11779         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11780         rsurface.batchnormal3f = rsurface.modelnormal3f;
11781         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11782         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11783         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11784         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11785         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11786         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11787         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11788         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11789         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11790         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11791         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11792         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
11793         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11794         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11795         rsurface.batchelement3i = rsurface.modelelement3i;
11796         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11797         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11798         rsurface.batchelement3s = rsurface.modelelement3s;
11799         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11800         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11801
11802         // if any dynamic vertex processing has to occur in software, we copy the
11803         // entire surface list together before processing to rebase the vertices
11804         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11805         //
11806         // if any gaps exist and we do not have a static vertex buffer, we have to
11807         // copy the surface list together to avoid wasting upload bandwidth on the
11808         // vertices in the gaps.
11809         //
11810         // if gaps exist and we have a static vertex buffer, we still have to
11811         // combine the index buffer ranges into one dynamic index buffer.
11812         //
11813         // in all cases we end up with data that can be drawn in one call.
11814
11815         if (!dynamicvertex)
11816         {
11817                 // static vertex data, just set pointers...
11818                 rsurface.batchgeneratedvertex = false;
11819                 // if there are gaps, we want to build a combined index buffer,
11820                 // otherwise use the original static buffer with an appropriate offset
11821                 if (gaps)
11822                 {
11823                         // build a new triangle elements array for this batch
11824                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11825                         rsurface.batchfirsttriangle = 0;
11826                         numtriangles = 0;
11827                         for (i = 0;i < texturenumsurfaces;i++)
11828                         {
11829                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11830                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11831                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11832                                 numtriangles += surfacenumtriangles;
11833                         }
11834                         rsurface.batchelement3i_indexbuffer = NULL;
11835                         rsurface.batchelement3i_bufferoffset = 0;
11836                         rsurface.batchelement3s = NULL;
11837                         rsurface.batchelement3s_indexbuffer = NULL;
11838                         rsurface.batchelement3s_bufferoffset = 0;
11839                         if (endvertex <= 65536)
11840                         {
11841                                 // make a 16bit (unsigned short) index array if possible
11842                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11843                                 for (i = 0;i < numtriangles*3;i++)
11844                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11845                         }
11846                 }
11847                 return;
11848         }
11849
11850         // something needs software processing, do it for real...
11851         // we only directly handle separate array data in this case and then
11852         // generate interleaved data if needed...
11853         rsurface.batchgeneratedvertex = true;
11854
11855         // now copy the vertex data into a combined array and make an index array
11856         // (this is what Quake3 does all the time)
11857         //if (gaps || rsurface.batchfirstvertex)
11858         {
11859                 rsurface.batchvertex3fbuffer = NULL;
11860                 rsurface.batchvertexmesh = NULL;
11861                 rsurface.batchvertexmeshbuffer = NULL;
11862                 rsurface.batchvertex3f = NULL;
11863                 rsurface.batchvertex3f_vertexbuffer = NULL;
11864                 rsurface.batchvertex3f_bufferoffset = 0;
11865                 rsurface.batchsvector3f = NULL;
11866                 rsurface.batchsvector3f_vertexbuffer = NULL;
11867                 rsurface.batchsvector3f_bufferoffset = 0;
11868                 rsurface.batchtvector3f = NULL;
11869                 rsurface.batchtvector3f_vertexbuffer = NULL;
11870                 rsurface.batchtvector3f_bufferoffset = 0;
11871                 rsurface.batchnormal3f = NULL;
11872                 rsurface.batchnormal3f_vertexbuffer = NULL;
11873                 rsurface.batchnormal3f_bufferoffset = 0;
11874                 rsurface.batchlightmapcolor4f = NULL;
11875                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11876                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11877                 rsurface.batchtexcoordtexture2f = NULL;
11878                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11879                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11880                 rsurface.batchtexcoordlightmap2f = NULL;
11881                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11882                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11883                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11884                 rsurface.batchelement3i_indexbuffer = NULL;
11885                 rsurface.batchelement3i_bufferoffset = 0;
11886                 rsurface.batchelement3s = NULL;
11887                 rsurface.batchelement3s_indexbuffer = NULL;
11888                 rsurface.batchelement3s_bufferoffset = 0;
11889                 // we'll only be setting up certain arrays as needed
11890                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11891                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11892                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11893                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11894                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11895                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11896                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11897                 {
11898                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11899                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11900                 }
11901                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11902                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11903                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11904                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11905                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11906                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11907                 numvertices = 0;
11908                 numtriangles = 0;
11909                 for (i = 0;i < texturenumsurfaces;i++)
11910                 {
11911                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11912                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11913                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11914                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11915                         // copy only the data requested
11916                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11917                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11918                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11919                         {
11920                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11921                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11922                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11923                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11924                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11925                                 {
11926                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11927                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11928                                 }
11929                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11930                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11931                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11932                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11933                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11934                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11935                         }
11936                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11937                         numvertices += surfacenumvertices;
11938                         numtriangles += surfacenumtriangles;
11939                 }
11940
11941                 // generate a 16bit index array as well if possible
11942                 // (in general, dynamic batches fit)
11943                 if (numvertices <= 65536)
11944                 {
11945                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11946                         for (i = 0;i < numtriangles*3;i++)
11947                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11948                 }
11949
11950                 // since we've copied everything, the batch now starts at 0
11951                 rsurface.batchfirstvertex = 0;
11952                 rsurface.batchnumvertices = batchnumvertices;
11953                 rsurface.batchfirsttriangle = 0;
11954                 rsurface.batchnumtriangles = batchnumtriangles;
11955         }
11956
11957         // q1bsp surfaces rendered in vertex color mode have to have colors
11958         // calculated based on lightstyles
11959         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11960         {
11961                 // generate color arrays for the surfaces in this list
11962                 int c[4];
11963                 int scale;
11964                 int size3;
11965                 const int *offsets;
11966                 const unsigned char *lm;
11967                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11968                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11969                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11970                 numvertices = 0;
11971                 for (i = 0;i < texturenumsurfaces;i++)
11972                 {
11973                         surface = texturesurfacelist[i];
11974                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11975                         surfacenumvertices = surface->num_vertices;
11976                         if (surface->lightmapinfo->samples)
11977                         {
11978                                 for (j = 0;j < surfacenumvertices;j++)
11979                                 {
11980                                         lm = surface->lightmapinfo->samples + offsets[j];
11981                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11982                                         VectorScale(lm, scale, c);
11983                                         if (surface->lightmapinfo->styles[1] != 255)
11984                                         {
11985                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11986                                                 lm += size3;
11987                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11988                                                 VectorMA(c, scale, lm, c);
11989                                                 if (surface->lightmapinfo->styles[2] != 255)
11990                                                 {
11991                                                         lm += size3;
11992                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11993                                                         VectorMA(c, scale, lm, c);
11994                                                         if (surface->lightmapinfo->styles[3] != 255)
11995                                                         {
11996                                                                 lm += size3;
11997                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11998                                                                 VectorMA(c, scale, lm, c);
11999                                                         }
12000                                                 }
12001                                         }
12002                                         c[0] >>= 7;
12003                                         c[1] >>= 7;
12004                                         c[2] >>= 7;
12005                                         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);
12006                                         numvertices++;
12007                                 }
12008                         }
12009                         else
12010                         {
12011                                 for (j = 0;j < surfacenumvertices;j++)
12012                                 {
12013                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
12014                                         numvertices++;
12015                                 }
12016                         }
12017                 }
12018         }
12019
12020         // if vertices are deformed (sprite flares and things in maps, possibly
12021         // water waves, bulges and other deformations), modify the copied vertices
12022         // in place
12023         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
12024         {
12025                 switch (deform->deform)
12026                 {
12027                 default:
12028                 case Q3DEFORM_PROJECTIONSHADOW:
12029                 case Q3DEFORM_TEXT0:
12030                 case Q3DEFORM_TEXT1:
12031                 case Q3DEFORM_TEXT2:
12032                 case Q3DEFORM_TEXT3:
12033                 case Q3DEFORM_TEXT4:
12034                 case Q3DEFORM_TEXT5:
12035                 case Q3DEFORM_TEXT6:
12036                 case Q3DEFORM_TEXT7:
12037                 case Q3DEFORM_NONE:
12038                         break;
12039                 case Q3DEFORM_AUTOSPRITE:
12040                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
12041                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
12042                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
12043                         VectorNormalize(newforward);
12044                         VectorNormalize(newright);
12045                         VectorNormalize(newup);
12046 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12047 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12048 //                      rsurface.batchvertex3f_bufferoffset = 0;
12049 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
12050 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
12051 //                      rsurface.batchsvector3f_bufferoffset = 0;
12052 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
12053 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
12054 //                      rsurface.batchtvector3f_bufferoffset = 0;
12055 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12056 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
12057 //                      rsurface.batchnormal3f_bufferoffset = 0;
12058                         // a single autosprite surface can contain multiple sprites...
12059                         for (j = 0;j < batchnumvertices - 3;j += 4)
12060                         {
12061                                 VectorClear(center);
12062                                 for (i = 0;i < 4;i++)
12063                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
12064                                 VectorScale(center, 0.25f, center);
12065                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
12066                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
12067                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
12068                                 for (i = 0;i < 4;i++)
12069                                 {
12070                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
12071                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
12072                                 }
12073                         }
12074                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
12075                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12076                         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);
12077                         break;
12078                 case Q3DEFORM_AUTOSPRITE2:
12079                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
12080                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
12081                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
12082                         VectorNormalize(newforward);
12083                         VectorNormalize(newright);
12084                         VectorNormalize(newup);
12085 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12086 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12087 //                      rsurface.batchvertex3f_bufferoffset = 0;
12088                         {
12089                                 const float *v1, *v2;
12090                                 vec3_t start, end;
12091                                 float f, l;
12092                                 struct
12093                                 {
12094                                         float length2;
12095                                         const float *v1;
12096                                         const float *v2;
12097                                 }
12098                                 shortest[2];
12099                                 memset(shortest, 0, sizeof(shortest));
12100                                 // a single autosprite surface can contain multiple sprites...
12101                                 for (j = 0;j < batchnumvertices - 3;j += 4)
12102                                 {
12103                                         VectorClear(center);
12104                                         for (i = 0;i < 4;i++)
12105                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
12106                                         VectorScale(center, 0.25f, center);
12107                                         // find the two shortest edges, then use them to define the
12108                                         // axis vectors for rotating around the central axis
12109                                         for (i = 0;i < 6;i++)
12110                                         {
12111                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
12112                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
12113                                                 l = VectorDistance2(v1, v2);
12114                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
12115                                                 if (v1[2] != v2[2])
12116                                                         l += (1.0f / 1024.0f);
12117                                                 if (shortest[0].length2 > l || i == 0)
12118                                                 {
12119                                                         shortest[1] = shortest[0];
12120                                                         shortest[0].length2 = l;
12121                                                         shortest[0].v1 = v1;
12122                                                         shortest[0].v2 = v2;
12123                                                 }
12124                                                 else if (shortest[1].length2 > l || i == 1)
12125                                                 {
12126                                                         shortest[1].length2 = l;
12127                                                         shortest[1].v1 = v1;
12128                                                         shortest[1].v2 = v2;
12129                                                 }
12130                                         }
12131                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
12132                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
12133                                         // this calculates the right vector from the shortest edge
12134                                         // and the up vector from the edge midpoints
12135                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
12136                                         VectorNormalize(right);
12137                                         VectorSubtract(end, start, up);
12138                                         VectorNormalize(up);
12139                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
12140                                         VectorSubtract(rsurface.localvieworigin, center, forward);
12141                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
12142                                         VectorNegate(forward, forward);
12143                                         VectorReflect(forward, 0, up, forward);
12144                                         VectorNormalize(forward);
12145                                         CrossProduct(up, forward, newright);
12146                                         VectorNormalize(newright);
12147                                         // rotate the quad around the up axis vector, this is made
12148                                         // especially easy by the fact we know the quad is flat,
12149                                         // so we only have to subtract the center position and
12150                                         // measure distance along the right vector, and then
12151                                         // multiply that by the newright vector and add back the
12152                                         // center position
12153                                         // we also need to subtract the old position to undo the
12154                                         // displacement from the center, which we do with a
12155                                         // DotProduct, the subtraction/addition of center is also
12156                                         // optimized into DotProducts here
12157                                         l = DotProduct(right, center);
12158                                         for (i = 0;i < 4;i++)
12159                                         {
12160                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
12161                                                 f = DotProduct(right, v1) - l;
12162                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
12163                                         }
12164                                 }
12165                         }
12166                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
12167                         {
12168 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12169 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
12170 //                              rsurface.batchnormal3f_bufferoffset = 0;
12171                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12172                         }
12173                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12174                         {
12175 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12176 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12177 //                              rsurface.batchsvector3f_bufferoffset = 0;
12178 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12179 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12180 //                              rsurface.batchtvector3f_bufferoffset = 0;
12181                                 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);
12182                         }
12183                         break;
12184                 case Q3DEFORM_NORMAL:
12185                         // deform the normals to make reflections wavey
12186                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12187                         rsurface.batchnormal3f_vertexbuffer = NULL;
12188                         rsurface.batchnormal3f_bufferoffset = 0;
12189                         for (j = 0;j < batchnumvertices;j++)
12190                         {
12191                                 float vertex[3];
12192                                 float *normal = rsurface.batchnormal3f + 3*j;
12193                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
12194                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
12195                                 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]);
12196                                 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]);
12197                                 VectorNormalize(normal);
12198                         }
12199                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12200                         {
12201 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12202 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12203 //                              rsurface.batchsvector3f_bufferoffset = 0;
12204 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12205 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12206 //                              rsurface.batchtvector3f_bufferoffset = 0;
12207                                 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);
12208                         }
12209                         break;
12210                 case Q3DEFORM_WAVE:
12211                         // deform vertex array to make wavey water and flags and such
12212                         waveparms[0] = deform->waveparms[0];
12213                         waveparms[1] = deform->waveparms[1];
12214                         waveparms[2] = deform->waveparms[2];
12215                         waveparms[3] = deform->waveparms[3];
12216                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
12217                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12218                         // this is how a divisor of vertex influence on deformation
12219                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
12220                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12221 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12222 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12223 //                      rsurface.batchvertex3f_bufferoffset = 0;
12224 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12225 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
12226 //                      rsurface.batchnormal3f_bufferoffset = 0;
12227                         for (j = 0;j < batchnumvertices;j++)
12228                         {
12229                                 // if the wavefunc depends on time, evaluate it per-vertex
12230                                 if (waveparms[3])
12231                                 {
12232                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
12233                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12234                                 }
12235                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
12236                         }
12237                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12238                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12239                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12240                         {
12241 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12242 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12243 //                              rsurface.batchsvector3f_bufferoffset = 0;
12244 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12245 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12246 //                              rsurface.batchtvector3f_bufferoffset = 0;
12247                                 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);
12248                         }
12249                         break;
12250                 case Q3DEFORM_BULGE:
12251                         // deform vertex array to make the surface have moving bulges
12252 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12253 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12254 //                      rsurface.batchvertex3f_bufferoffset = 0;
12255 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12256 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
12257 //                      rsurface.batchnormal3f_bufferoffset = 0;
12258                         for (j = 0;j < batchnumvertices;j++)
12259                         {
12260                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12261                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
12262                         }
12263                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12264                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12265                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12266                         {
12267 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12268 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12269 //                              rsurface.batchsvector3f_bufferoffset = 0;
12270 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12271 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12272 //                              rsurface.batchtvector3f_bufferoffset = 0;
12273                                 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);
12274                         }
12275                         break;
12276                 case Q3DEFORM_MOVE:
12277                         // deform vertex array
12278                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12279                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12280                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12281                         VectorScale(deform->parms, scale, waveparms);
12282 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12283 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12284 //                      rsurface.batchvertex3f_bufferoffset = 0;
12285                         for (j = 0;j < batchnumvertices;j++)
12286                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
12287                         break;
12288                 }
12289         }
12290
12291         // generate texcoords based on the chosen texcoord source
12292         switch(rsurface.texture->tcgen.tcgen)
12293         {
12294         default:
12295         case Q3TCGEN_TEXTURE:
12296                 break;
12297         case Q3TCGEN_LIGHTMAP:
12298 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12299 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12300 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12301                 if (rsurface.batchtexcoordlightmap2f)
12302                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
12303                 break;
12304         case Q3TCGEN_VECTOR:
12305 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12306 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12307 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12308                 for (j = 0;j < batchnumvertices;j++)
12309                 {
12310                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12311                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12312                 }
12313                 break;
12314         case Q3TCGEN_ENVIRONMENT:
12315                 // make environment reflections using a spheremap
12316                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12317                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12318                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12319                 for (j = 0;j < batchnumvertices;j++)
12320                 {
12321                         // identical to Q3A's method, but executed in worldspace so
12322                         // carried models can be shiny too
12323
12324                         float viewer[3], d, reflected[3], worldreflected[3];
12325
12326                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12327                         // VectorNormalize(viewer);
12328
12329                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12330
12331                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12332                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12333                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12334                         // note: this is proportinal to viewer, so we can normalize later
12335
12336                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12337                         VectorNormalize(worldreflected);
12338
12339                         // note: this sphere map only uses world x and z!
12340                         // so positive and negative y will LOOK THE SAME.
12341                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12342                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12343                 }
12344                 break;
12345         }
12346         // the only tcmod that needs software vertex processing is turbulent, so
12347         // check for it here and apply the changes if needed
12348         // and we only support that as the first one
12349         // (handling a mixture of turbulent and other tcmods would be problematic
12350         //  without punting it entirely to a software path)
12351         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12352         {
12353                 amplitude = rsurface.texture->tcmods[0].parms[1];
12354                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12355 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12356 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12357 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12358                 for (j = 0;j < batchnumvertices;j++)
12359                 {
12360                         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);
12361                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12362                 }
12363         }
12364
12365         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12366         {
12367                 // convert the modified arrays to vertex structs
12368 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
12369 //              rsurface.batchvertexmeshbuffer = NULL;
12370                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12371                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12372                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12373                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12374                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12375                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12376                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12377                 {
12378                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12379                         {
12380                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12381                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12382                         }
12383                 }
12384                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12385                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12386                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12387                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12388                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12389                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12390                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12391                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12392                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12393         }
12394 }
12395
12396 void RSurf_DrawBatch(void)
12397 {
12398         // sometimes a zero triangle surface (usually a degenerate patch) makes it
12399         // through the pipeline, killing it earlier in the pipeline would have
12400         // per-surface overhead rather than per-batch overhead, so it's best to
12401         // reject it here, before it hits glDraw.
12402         if (rsurface.batchnumtriangles == 0)
12403                 return;
12404 #if 0
12405         // batch debugging code
12406         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
12407         {
12408                 int i;
12409                 int j;
12410                 int c;
12411                 const int *e;
12412                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
12413                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
12414                 {
12415                         c = e[i];
12416                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
12417                         {
12418                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
12419                                 {
12420                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
12421                                                 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);
12422                                         break;
12423                                 }
12424                         }
12425                 }
12426         }
12427 #endif
12428         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);
12429 }
12430
12431 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12432 {
12433         // pick the closest matching water plane
12434         int planeindex, vertexindex, bestplaneindex = -1;
12435         float d, bestd;
12436         vec3_t vert;
12437         const float *v;
12438         r_waterstate_waterplane_t *p;
12439         qboolean prepared = false;
12440         bestd = 0;
12441         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12442         {
12443                 if(p->camera_entity != rsurface.texture->camera_entity)
12444                         continue;
12445                 d = 0;
12446                 if(!prepared)
12447                 {
12448                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12449                         prepared = true;
12450                         if(rsurface.batchnumvertices == 0)
12451                                 break;
12452                 }
12453                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12454                 {
12455                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12456                         d += fabs(PlaneDiff(vert, &p->plane));
12457                 }
12458                 if (bestd > d || bestplaneindex < 0)
12459                 {
12460                         bestd = d;
12461                         bestplaneindex = planeindex;
12462                 }
12463         }
12464         return bestplaneindex;
12465         // NOTE: this MAY return a totally unrelated water plane; we can ignore
12466         // this situation though, as it might be better to render single larger
12467         // batches with useless stuff (backface culled for example) than to
12468         // render multiple smaller batches
12469 }
12470
12471 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12472 {
12473         int i;
12474         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12475         rsurface.passcolor4f_vertexbuffer = 0;
12476         rsurface.passcolor4f_bufferoffset = 0;
12477         for (i = 0;i < rsurface.batchnumvertices;i++)
12478                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12479 }
12480
12481 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12482 {
12483         int i;
12484         float f;
12485         const float *v;
12486         const float *c;
12487         float *c2;
12488         if (rsurface.passcolor4f)
12489         {
12490                 // generate color arrays
12491                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
12492                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12493                 rsurface.passcolor4f_vertexbuffer = 0;
12494                 rsurface.passcolor4f_bufferoffset = 0;
12495                 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)
12496                 {
12497                         f = RSurf_FogVertex(v);
12498                         c2[0] = c[0] * f;
12499                         c2[1] = c[1] * f;
12500                         c2[2] = c[2] * f;
12501                         c2[3] = c[3];
12502                 }
12503         }
12504         else
12505         {
12506                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12507                 rsurface.passcolor4f_vertexbuffer = 0;
12508                 rsurface.passcolor4f_bufferoffset = 0;
12509                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12510                 {
12511                         f = RSurf_FogVertex(v);
12512                         c2[0] = f;
12513                         c2[1] = f;
12514                         c2[2] = f;
12515                         c2[3] = 1;
12516                 }
12517         }
12518 }
12519
12520 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12521 {
12522         int i;
12523         float f;
12524         const float *v;
12525         const float *c;
12526         float *c2;
12527         if (!rsurface.passcolor4f)
12528                 return;
12529         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
12530         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12531         rsurface.passcolor4f_vertexbuffer = 0;
12532         rsurface.passcolor4f_bufferoffset = 0;
12533         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)
12534         {
12535                 f = RSurf_FogVertex(v);
12536                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12537                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12538                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12539                 c2[3] = c[3];
12540         }
12541 }
12542
12543 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12544 {
12545         int i;
12546         const float *c;
12547         float *c2;
12548         if (!rsurface.passcolor4f)
12549                 return;
12550         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
12551         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12552         rsurface.passcolor4f_vertexbuffer = 0;
12553         rsurface.passcolor4f_bufferoffset = 0;
12554         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12555         {
12556                 c2[0] = c[0] * r;
12557                 c2[1] = c[1] * g;
12558                 c2[2] = c[2] * b;
12559                 c2[3] = c[3] * a;
12560         }
12561 }
12562
12563 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12564 {
12565         int i;
12566         const float *c;
12567         float *c2;
12568         if (!rsurface.passcolor4f)
12569                 return;
12570         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
12571         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12572         rsurface.passcolor4f_vertexbuffer = 0;
12573         rsurface.passcolor4f_bufferoffset = 0;
12574         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12575         {
12576                 c2[0] = c[0] + r_refdef.scene.ambient;
12577                 c2[1] = c[1] + r_refdef.scene.ambient;
12578                 c2[2] = c[2] + r_refdef.scene.ambient;
12579                 c2[3] = c[3];
12580         }
12581 }
12582
12583 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12584 {
12585         // TODO: optimize
12586         rsurface.passcolor4f = NULL;
12587         rsurface.passcolor4f_vertexbuffer = 0;
12588         rsurface.passcolor4f_bufferoffset = 0;
12589         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12590         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12591         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12592         GL_Color(r, g, b, a);
12593         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12594         RSurf_DrawBatch();
12595 }
12596
12597 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12598 {
12599         // TODO: optimize applyfog && applycolor case
12600         // just apply fog if necessary, and tint the fog color array if necessary
12601         rsurface.passcolor4f = NULL;
12602         rsurface.passcolor4f_vertexbuffer = 0;
12603         rsurface.passcolor4f_bufferoffset = 0;
12604         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12605         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12606         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12607         GL_Color(r, g, b, a);
12608         RSurf_DrawBatch();
12609 }
12610
12611 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12612 {
12613         // TODO: optimize
12614         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12615         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12616         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12617         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12618         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12619         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12620         GL_Color(r, g, b, a);
12621         RSurf_DrawBatch();
12622 }
12623
12624 static void RSurf_DrawBatch_GL11_ClampColor(void)
12625 {
12626         int i;
12627         const float *c1;
12628         float *c2;
12629         if (!rsurface.passcolor4f)
12630                 return;
12631         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12632         {
12633                 c2[0] = bound(0.0f, c1[0], 1.0f);
12634                 c2[1] = bound(0.0f, c1[1], 1.0f);
12635                 c2[2] = bound(0.0f, c1[2], 1.0f);
12636                 c2[3] = bound(0.0f, c1[3], 1.0f);
12637         }
12638 }
12639
12640 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12641 {
12642         int i;
12643         float f;
12644         const float *v;
12645         const float *n;
12646         float *c;
12647         //vec3_t eyedir;
12648
12649         // fake shading
12650         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12651         rsurface.passcolor4f_vertexbuffer = 0;
12652         rsurface.passcolor4f_bufferoffset = 0;
12653         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
12654         {
12655                 f = -DotProduct(r_refdef.view.forward, n);
12656                 f = max(0, f);
12657                 f = f * 0.85 + 0.15; // work around so stuff won't get black
12658                 f *= r_refdef.lightmapintensity;
12659                 Vector4Set(c, f, f, f, 1);
12660         }
12661 }
12662
12663 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12664 {
12665         RSurf_DrawBatch_GL11_ApplyFakeLight();
12666         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12667         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12668         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12669         GL_Color(r, g, b, a);
12670         RSurf_DrawBatch();
12671 }
12672
12673 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12674 {
12675         int i;
12676         float f;
12677         float alpha;
12678         const float *v;
12679         const float *n;
12680         float *c;
12681         vec3_t ambientcolor;
12682         vec3_t diffusecolor;
12683         vec3_t lightdir;
12684         // TODO: optimize
12685         // model lighting
12686         VectorCopy(rsurface.modellight_lightdir, lightdir);
12687         f = 0.5f * r_refdef.lightmapintensity;
12688         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12689         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12690         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12691         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12692         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12693         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12694         alpha = *a;
12695         if (VectorLength2(diffusecolor) > 0)
12696         {
12697                 // q3-style directional shading
12698                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12699                 rsurface.passcolor4f_vertexbuffer = 0;
12700                 rsurface.passcolor4f_bufferoffset = 0;
12701                 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)
12702                 {
12703                         if ((f = DotProduct(n, lightdir)) > 0)
12704                                 VectorMA(ambientcolor, f, diffusecolor, c);
12705                         else
12706                                 VectorCopy(ambientcolor, c);
12707                         c[3] = alpha;
12708                 }
12709                 *r = 1;
12710                 *g = 1;
12711                 *b = 1;
12712                 *a = 1;
12713                 *applycolor = false;
12714         }
12715         else
12716         {
12717                 *r = ambientcolor[0];
12718                 *g = ambientcolor[1];
12719                 *b = ambientcolor[2];
12720                 rsurface.passcolor4f = NULL;
12721                 rsurface.passcolor4f_vertexbuffer = 0;
12722                 rsurface.passcolor4f_bufferoffset = 0;
12723         }
12724 }
12725
12726 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12727 {
12728         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12729         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12730         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12731         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12732         GL_Color(r, g, b, a);
12733         RSurf_DrawBatch();
12734 }
12735
12736 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12737 {
12738         int i;
12739         float f;
12740         const float *v;
12741         float *c;
12742         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12743         {
12744                 f = 1 - RSurf_FogVertex(v);
12745                 c[0] = r;
12746                 c[1] = g;
12747                 c[2] = b;
12748                 c[3] = f * a;
12749         }
12750 }
12751
12752 void RSurf_SetupDepthAndCulling(void)
12753 {
12754         // submodels are biased to avoid z-fighting with world surfaces that they
12755         // may be exactly overlapping (avoids z-fighting artifacts on certain
12756         // doors and things in Quake maps)
12757         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12758         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12759         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12760         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12761 }
12762
12763 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12764 {
12765         // transparent sky would be ridiculous
12766         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12767                 return;
12768         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12769         skyrenderlater = true;
12770         RSurf_SetupDepthAndCulling();
12771         GL_DepthMask(true);
12772         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12773         // skymasking on them, and Quake3 never did sky masking (unlike
12774         // software Quake and software Quake2), so disable the sky masking
12775         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12776         // and skymasking also looks very bad when noclipping outside the
12777         // level, so don't use it then either.
12778         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12779         {
12780                 R_Mesh_ResetTextureState();
12781                 if (skyrendermasked)
12782                 {
12783                         R_SetupShader_DepthOrShadow();
12784                         // depth-only (masking)
12785                         GL_ColorMask(0,0,0,0);
12786                         // just to make sure that braindead drivers don't draw
12787                         // anything despite that colormask...
12788                         GL_BlendFunc(GL_ZERO, GL_ONE);
12789                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12790                         if (rsurface.batchvertex3fbuffer)
12791                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12792                         else
12793                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12794                 }
12795                 else
12796                 {
12797                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12798                         // fog sky
12799                         GL_BlendFunc(GL_ONE, GL_ZERO);
12800                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12801                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12802                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12803                 }
12804                 RSurf_DrawBatch();
12805                 if (skyrendermasked)
12806                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12807         }
12808         R_Mesh_ResetTextureState();
12809         GL_Color(1, 1, 1, 1);
12810 }
12811
12812 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12813 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12814 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12815 {
12816         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12817                 return;
12818         if (prepass)
12819         {
12820                 // render screenspace normalmap to texture
12821                 GL_DepthMask(true);
12822                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12823                 RSurf_DrawBatch();
12824                 return;
12825         }
12826
12827         // bind lightmap texture
12828
12829         // water/refraction/reflection/camera surfaces have to be handled specially
12830         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12831         {
12832                 int start, end, startplaneindex;
12833                 for (start = 0;start < texturenumsurfaces;start = end)
12834                 {
12835                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12836                         if(startplaneindex < 0)
12837                         {
12838                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12839                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12840                                 end = start + 1;
12841                                 continue;
12842                         }
12843                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12844                                 ;
12845                         // now that we have a batch using the same planeindex, render it
12846                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12847                         {
12848                                 // render water or distortion background
12849                                 GL_DepthMask(true);
12850                                 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));
12851                                 RSurf_DrawBatch();
12852                                 // blend surface on top
12853                                 GL_DepthMask(false);
12854                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12855                                 RSurf_DrawBatch();
12856                         }
12857                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12858                         {
12859                                 // render surface with reflection texture as input
12860                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12861                                 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));
12862                                 RSurf_DrawBatch();
12863                         }
12864                 }
12865                 return;
12866         }
12867
12868         // render surface batch normally
12869         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12870         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12871         RSurf_DrawBatch();
12872 }
12873
12874 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12875 {
12876         // OpenGL 1.3 path - anything not completely ancient
12877         qboolean applycolor;
12878         qboolean applyfog;
12879         int layerindex;
12880         const texturelayer_t *layer;
12881         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);
12882         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12883
12884         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12885         {
12886                 vec4_t layercolor;
12887                 int layertexrgbscale;
12888                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12889                 {
12890                         if (layerindex == 0)
12891                                 GL_AlphaTest(true);
12892                         else
12893                         {
12894                                 GL_AlphaTest(false);
12895                                 GL_DepthFunc(GL_EQUAL);
12896                         }
12897                 }
12898                 GL_DepthMask(layer->depthmask && writedepth);
12899                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12900                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12901                 {
12902                         layertexrgbscale = 4;
12903                         VectorScale(layer->color, 0.25f, layercolor);
12904                 }
12905                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12906                 {
12907                         layertexrgbscale = 2;
12908                         VectorScale(layer->color, 0.5f, layercolor);
12909                 }
12910                 else
12911                 {
12912                         layertexrgbscale = 1;
12913                         VectorScale(layer->color, 1.0f, layercolor);
12914                 }
12915                 layercolor[3] = layer->color[3];
12916                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12917                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12918                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12919                 switch (layer->type)
12920                 {
12921                 case TEXTURELAYERTYPE_LITTEXTURE:
12922                         // single-pass lightmapped texture with 2x rgbscale
12923                         R_Mesh_TexBind(0, r_texture_white);
12924                         R_Mesh_TexMatrix(0, NULL);
12925                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12926                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12927                         R_Mesh_TexBind(1, layer->texture);
12928                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12929                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12930                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12931                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12932                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12933                         else if (FAKELIGHT_ENABLED)
12934                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12935                         else if (rsurface.uselightmaptexture)
12936                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12937                         else
12938                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12939                         break;
12940                 case TEXTURELAYERTYPE_TEXTURE:
12941                         // singletexture unlit texture with transparency support
12942                         R_Mesh_TexBind(0, layer->texture);
12943                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12944                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12945                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12946                         R_Mesh_TexBind(1, 0);
12947                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12948                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12949                         break;
12950                 case TEXTURELAYERTYPE_FOG:
12951                         // singletexture fogging
12952                         if (layer->texture)
12953                         {
12954                                 R_Mesh_TexBind(0, layer->texture);
12955                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12956                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12957                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12958                         }
12959                         else
12960                         {
12961                                 R_Mesh_TexBind(0, 0);
12962                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12963                         }
12964                         R_Mesh_TexBind(1, 0);
12965                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12966                         // generate a color array for the fog pass
12967                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12968                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12969                         RSurf_DrawBatch();
12970                         break;
12971                 default:
12972                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12973                 }
12974         }
12975         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12976         {
12977                 GL_DepthFunc(GL_LEQUAL);
12978                 GL_AlphaTest(false);
12979         }
12980 }
12981
12982 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12983 {
12984         // OpenGL 1.1 - crusty old voodoo path
12985         qboolean applyfog;
12986         int layerindex;
12987         const texturelayer_t *layer;
12988         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);
12989         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12990
12991         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12992         {
12993                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12994                 {
12995                         if (layerindex == 0)
12996                                 GL_AlphaTest(true);
12997                         else
12998                         {
12999                                 GL_AlphaTest(false);
13000                                 GL_DepthFunc(GL_EQUAL);
13001                         }
13002                 }
13003                 GL_DepthMask(layer->depthmask && writedepth);
13004                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
13005                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
13006                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
13007                 switch (layer->type)
13008                 {
13009                 case TEXTURELAYERTYPE_LITTEXTURE:
13010                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
13011                         {
13012                                 // two-pass lit texture with 2x rgbscale
13013                                 // first the lightmap pass
13014                                 R_Mesh_TexBind(0, r_texture_white);
13015                                 R_Mesh_TexMatrix(0, NULL);
13016                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
13017                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
13018                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
13019                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
13020                                 else if (FAKELIGHT_ENABLED)
13021                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
13022                                 else if (rsurface.uselightmaptexture)
13023                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
13024                                 else
13025                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
13026                                 // then apply the texture to it
13027                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
13028                                 R_Mesh_TexBind(0, layer->texture);
13029                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
13030                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
13031                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
13032                                 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);
13033                         }
13034                         else
13035                         {
13036                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
13037                                 R_Mesh_TexBind(0, layer->texture);
13038                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
13039                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
13040                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
13041                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
13042                                         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);
13043                                 else
13044                                         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);
13045                         }
13046                         break;
13047                 case TEXTURELAYERTYPE_TEXTURE:
13048                         // singletexture unlit texture with transparency support
13049                         R_Mesh_TexBind(0, layer->texture);
13050                         R_Mesh_TexMatrix(0, &layer->texmatrix);
13051                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
13052                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
13053                         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);
13054                         break;
13055                 case TEXTURELAYERTYPE_FOG:
13056                         // singletexture fogging
13057                         if (layer->texture)
13058                         {
13059                                 R_Mesh_TexBind(0, layer->texture);
13060                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
13061                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
13062                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
13063                         }
13064                         else
13065                         {
13066                                 R_Mesh_TexBind(0, 0);
13067                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
13068                         }
13069                         // generate a color array for the fog pass
13070                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
13071                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
13072                         RSurf_DrawBatch();
13073                         break;
13074                 default:
13075                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
13076                 }
13077         }
13078         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
13079         {
13080                 GL_DepthFunc(GL_LEQUAL);
13081                 GL_AlphaTest(false);
13082         }
13083 }
13084
13085 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
13086 {
13087         int vi;
13088         int j;
13089         r_vertexgeneric_t *batchvertex;
13090         float c[4];
13091
13092 //      R_Mesh_ResetTextureState();
13093         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13094
13095         if(rsurface.texture && rsurface.texture->currentskinframe)
13096         {
13097                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
13098                 c[3] *= rsurface.texture->currentalpha;
13099         }
13100         else
13101         {
13102                 c[0] = 1;
13103                 c[1] = 0;
13104                 c[2] = 1;
13105                 c[3] = 1;
13106         }
13107
13108         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
13109         {
13110                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
13111                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
13112                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
13113         }
13114
13115         // brighten it up (as texture value 127 means "unlit")
13116         c[0] *= 2 * r_refdef.view.colorscale;
13117         c[1] *= 2 * r_refdef.view.colorscale;
13118         c[2] *= 2 * r_refdef.view.colorscale;
13119
13120         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
13121                 c[3] *= r_wateralpha.value;
13122
13123         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
13124         {
13125                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13126                 GL_DepthMask(false);
13127         }
13128         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
13129         {
13130                 GL_BlendFunc(GL_ONE, GL_ONE);
13131                 GL_DepthMask(false);
13132         }
13133         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
13134         {
13135                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
13136                 GL_DepthMask(false);
13137         }
13138         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
13139         {
13140                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
13141                 GL_DepthMask(false);
13142         }
13143         else
13144         {
13145                 GL_BlendFunc(GL_ONE, GL_ZERO);
13146                 GL_DepthMask(writedepth);
13147         }
13148
13149         if (r_showsurfaces.integer == 3)
13150         {
13151                 rsurface.passcolor4f = NULL;
13152
13153                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
13154                 {
13155                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13156
13157                         rsurface.passcolor4f = NULL;
13158                         rsurface.passcolor4f_vertexbuffer = 0;
13159                         rsurface.passcolor4f_bufferoffset = 0;
13160                 }
13161                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
13162                 {
13163                         qboolean applycolor = true;
13164                         float one = 1.0;
13165
13166                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13167
13168                         r_refdef.lightmapintensity = 1;
13169                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
13170                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
13171                 }
13172                 else if (FAKELIGHT_ENABLED)
13173                 {
13174                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13175
13176                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
13177                         RSurf_DrawBatch_GL11_ApplyFakeLight();
13178                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
13179                 }
13180                 else
13181                 {
13182                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13183
13184                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
13185                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
13186                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
13187                 }
13188
13189                 if(!rsurface.passcolor4f)
13190                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
13191
13192                 RSurf_DrawBatch_GL11_ApplyAmbient();
13193                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
13194                 if(r_refdef.fogenabled)
13195                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
13196                 RSurf_DrawBatch_GL11_ClampColor();
13197
13198                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
13199                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13200                 RSurf_DrawBatch();
13201         }
13202         else if (!r_refdef.view.showdebug)
13203         {
13204                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13205                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13206                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13207                 {
13208                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13209                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
13210                 }
13211                 R_Mesh_PrepareVertices_Generic_Unlock();
13212                 RSurf_DrawBatch();
13213         }
13214         else if (r_showsurfaces.integer == 4)
13215         {
13216                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13217                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13218                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13219                 {
13220                         unsigned char c = vi << 3;
13221                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13222                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
13223                 }
13224                 R_Mesh_PrepareVertices_Generic_Unlock();
13225                 RSurf_DrawBatch();
13226         }
13227         else if (r_showsurfaces.integer == 2)
13228         {
13229                 const int *e;
13230                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13231                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
13232                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
13233                 {
13234                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
13235                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
13236                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
13237                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
13238                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
13239                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
13240                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
13241                 }
13242                 R_Mesh_PrepareVertices_Generic_Unlock();
13243                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
13244         }
13245         else
13246         {
13247                 int texturesurfaceindex;
13248                 int k;
13249                 const msurface_t *surface;
13250                 unsigned char surfacecolor4ub[4];
13251                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13252                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
13253                 vi = 0;
13254                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
13255                 {
13256                         surface = texturesurfacelist[texturesurfaceindex];
13257                         k = (int)(((size_t)surface) / sizeof(msurface_t));
13258                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
13259                         for (j = 0;j < surface->num_vertices;j++)
13260                         {
13261                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13262                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
13263                                 vi++;
13264                         }
13265                 }
13266                 R_Mesh_PrepareVertices_Generic_Unlock();
13267                 RSurf_DrawBatch();
13268         }
13269 }
13270
13271 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13272 {
13273         CHECKGLERROR
13274         RSurf_SetupDepthAndCulling();
13275         if (r_showsurfaces.integer)
13276         {
13277                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13278                 return;
13279         }
13280         switch (vid.renderpath)
13281         {
13282         case RENDERPATH_GL20:
13283         case RENDERPATH_CGGL:
13284         case RENDERPATH_D3D9:
13285         case RENDERPATH_D3D10:
13286         case RENDERPATH_D3D11:
13287         case RENDERPATH_SOFT:
13288         case RENDERPATH_GLES2:
13289                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13290                 break;
13291         case RENDERPATH_GL13:
13292                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13293                 break;
13294         case RENDERPATH_GL11:
13295                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13296                 break;
13297         }
13298         CHECKGLERROR
13299 }
13300
13301 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13302 {
13303         CHECKGLERROR
13304         RSurf_SetupDepthAndCulling();
13305         if (r_showsurfaces.integer)
13306         {
13307                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13308                 return;
13309         }
13310         switch (vid.renderpath)
13311         {
13312         case RENDERPATH_GL20:
13313         case RENDERPATH_CGGL:
13314         case RENDERPATH_D3D9:
13315         case RENDERPATH_D3D10:
13316         case RENDERPATH_D3D11:
13317         case RENDERPATH_SOFT:
13318         case RENDERPATH_GLES2:
13319                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13320                 break;
13321         case RENDERPATH_GL13:
13322                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13323                 break;
13324         case RENDERPATH_GL11:
13325                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13326                 break;
13327         }
13328         CHECKGLERROR
13329 }
13330
13331 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13332 {
13333         int i, j;
13334         int texturenumsurfaces, endsurface;
13335         texture_t *texture;
13336         const msurface_t *surface;
13337 #define MAXBATCH_TRANSPARENTSURFACES 256
13338         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13339
13340         // if the model is static it doesn't matter what value we give for
13341         // wantnormals and wanttangents, so this logic uses only rules applicable
13342         // to a model, knowing that they are meaningless otherwise
13343         if (ent == r_refdef.scene.worldentity)
13344                 RSurf_ActiveWorldEntity();
13345         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13346                 RSurf_ActiveModelEntity(ent, false, false, false);
13347         else
13348         {
13349                 switch (vid.renderpath)
13350                 {
13351                 case RENDERPATH_GL20:
13352                 case RENDERPATH_CGGL:
13353                 case RENDERPATH_D3D9:
13354                 case RENDERPATH_D3D10:
13355                 case RENDERPATH_D3D11:
13356                 case RENDERPATH_SOFT:
13357                 case RENDERPATH_GLES2:
13358                         RSurf_ActiveModelEntity(ent, true, true, false);
13359                         break;
13360                 case RENDERPATH_GL13:
13361                 case RENDERPATH_GL11:
13362                         RSurf_ActiveModelEntity(ent, true, false, false);
13363                         break;
13364                 }
13365         }
13366
13367         if (r_transparentdepthmasking.integer)
13368         {
13369                 qboolean setup = false;
13370                 for (i = 0;i < numsurfaces;i = j)
13371                 {
13372                         j = i + 1;
13373                         surface = rsurface.modelsurfaces + surfacelist[i];
13374                         texture = surface->texture;
13375                         rsurface.texture = R_GetCurrentTexture(texture);
13376                         rsurface.lightmaptexture = NULL;
13377                         rsurface.deluxemaptexture = NULL;
13378                         rsurface.uselightmaptexture = false;
13379                         // scan ahead until we find a different texture
13380                         endsurface = min(i + 1024, numsurfaces);
13381                         texturenumsurfaces = 0;
13382                         texturesurfacelist[texturenumsurfaces++] = surface;
13383                         for (;j < endsurface;j++)
13384                         {
13385                                 surface = rsurface.modelsurfaces + surfacelist[j];
13386                                 if (texture != surface->texture)
13387                                         break;
13388                                 texturesurfacelist[texturenumsurfaces++] = surface;
13389                         }
13390                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13391                                 continue;
13392                         // render the range of surfaces as depth
13393                         if (!setup)
13394                         {
13395                                 setup = true;
13396                                 GL_ColorMask(0,0,0,0);
13397                                 GL_Color(1,1,1,1);
13398                                 GL_DepthTest(true);
13399                                 GL_BlendFunc(GL_ONE, GL_ZERO);
13400                                 GL_DepthMask(true);
13401 //                              R_Mesh_ResetTextureState();
13402                                 R_SetupShader_DepthOrShadow();
13403                         }
13404                         RSurf_SetupDepthAndCulling();
13405                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
13406                         if (rsurface.batchvertex3fbuffer)
13407                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
13408                         else
13409                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
13410                         RSurf_DrawBatch();
13411                 }
13412                 if (setup)
13413                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13414         }
13415
13416         for (i = 0;i < numsurfaces;i = j)
13417         {
13418                 j = i + 1;
13419                 surface = rsurface.modelsurfaces + surfacelist[i];
13420                 texture = surface->texture;
13421                 rsurface.texture = R_GetCurrentTexture(texture);
13422                 // scan ahead until we find a different texture
13423                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13424                 texturenumsurfaces = 0;
13425                 texturesurfacelist[texturenumsurfaces++] = surface;
13426                 if(FAKELIGHT_ENABLED)
13427                 {
13428                         rsurface.lightmaptexture = NULL;
13429                         rsurface.deluxemaptexture = NULL;
13430                         rsurface.uselightmaptexture = false;
13431                         for (;j < endsurface;j++)
13432                         {
13433                                 surface = rsurface.modelsurfaces + surfacelist[j];
13434                                 if (texture != surface->texture)
13435                                         break;
13436                                 texturesurfacelist[texturenumsurfaces++] = surface;
13437                         }
13438                 }
13439                 else
13440                 {
13441                         rsurface.lightmaptexture = surface->lightmaptexture;
13442                         rsurface.deluxemaptexture = surface->deluxemaptexture;
13443                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13444                         for (;j < endsurface;j++)
13445                         {
13446                                 surface = rsurface.modelsurfaces + surfacelist[j];
13447                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13448                                         break;
13449                                 texturesurfacelist[texturenumsurfaces++] = surface;
13450                         }
13451                 }
13452                 // render the range of surfaces
13453                 if (ent == r_refdef.scene.worldentity)
13454                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13455                 else
13456                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13457         }
13458         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13459 }
13460
13461 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13462 {
13463         // transparent surfaces get pushed off into the transparent queue
13464         int surfacelistindex;
13465         const msurface_t *surface;
13466         vec3_t tempcenter, center;
13467         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13468         {
13469                 surface = texturesurfacelist[surfacelistindex];
13470                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13471                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13472                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13473                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13474                 if (queueentity->transparent_offset) // transparent offset
13475                 {
13476                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13477                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13478                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13479                 }
13480                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13481         }
13482 }
13483
13484 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13485 {
13486         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13487                 return;
13488         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13489                 return;
13490         RSurf_SetupDepthAndCulling();
13491         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
13492         if (rsurface.batchvertex3fbuffer)
13493                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
13494         else
13495                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
13496         RSurf_DrawBatch();
13497 }
13498
13499 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13500 {
13501         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13502         CHECKGLERROR
13503         if (depthonly)
13504                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13505         else if (prepass)
13506         {
13507                 if (!rsurface.texture->currentnumlayers)
13508                         return;
13509                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13510                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13511                 else
13512                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13513         }
13514         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13515                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13516         else if (!rsurface.texture->currentnumlayers)
13517                 return;
13518         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13519         {
13520                 // in the deferred case, transparent surfaces were queued during prepass
13521                 if (!r_shadow_usingdeferredprepass)
13522                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13523         }
13524         else
13525         {
13526                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13527                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13528         }
13529         CHECKGLERROR
13530 }
13531
13532 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13533 {
13534         int i, j;
13535         texture_t *texture;
13536         R_FrameData_SetMark();
13537         // break the surface list down into batches by texture and use of lightmapping
13538         for (i = 0;i < numsurfaces;i = j)
13539         {
13540                 j = i + 1;
13541                 // texture is the base texture pointer, rsurface.texture is the
13542                 // current frame/skin the texture is directing us to use (for example
13543                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13544                 // use skin 1 instead)
13545                 texture = surfacelist[i]->texture;
13546                 rsurface.texture = R_GetCurrentTexture(texture);
13547                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13548                 {
13549                         // if this texture is not the kind we want, skip ahead to the next one
13550                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13551                                 ;
13552                         continue;
13553                 }
13554                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13555                 {
13556                         rsurface.lightmaptexture = NULL;
13557                         rsurface.deluxemaptexture = NULL;
13558                         rsurface.uselightmaptexture = false;
13559                         // simply scan ahead until we find a different texture or lightmap state
13560                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13561                                 ;
13562                 }
13563                 else
13564                 {
13565                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13566                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13567                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13568                         // simply scan ahead until we find a different texture or lightmap state
13569                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13570                                 ;
13571                 }
13572                 // render the range of surfaces
13573                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13574         }
13575         R_FrameData_ReturnToMark();
13576 }
13577
13578 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13579 {
13580         CHECKGLERROR
13581         if (depthonly)
13582                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13583         else if (prepass)
13584         {
13585                 if (!rsurface.texture->currentnumlayers)
13586                         return;
13587                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13588                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13589                 else
13590                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13591         }
13592         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13593                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13594         else if (!rsurface.texture->currentnumlayers)
13595                 return;
13596         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13597         {
13598                 // in the deferred case, transparent surfaces were queued during prepass
13599                 if (!r_shadow_usingdeferredprepass)
13600                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13601         }
13602         else
13603         {
13604                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13605                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13606         }
13607         CHECKGLERROR
13608 }
13609
13610 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13611 {
13612         int i, j;
13613         texture_t *texture;
13614         R_FrameData_SetMark();
13615         // break the surface list down into batches by texture and use of lightmapping
13616         for (i = 0;i < numsurfaces;i = j)
13617         {
13618                 j = i + 1;
13619                 // texture is the base texture pointer, rsurface.texture is the
13620                 // current frame/skin the texture is directing us to use (for example
13621                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13622                 // use skin 1 instead)
13623                 texture = surfacelist[i]->texture;
13624                 rsurface.texture = R_GetCurrentTexture(texture);
13625                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13626                 {
13627                         // if this texture is not the kind we want, skip ahead to the next one
13628                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13629                                 ;
13630                         continue;
13631                 }
13632                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13633                 {
13634                         rsurface.lightmaptexture = NULL;
13635                         rsurface.deluxemaptexture = NULL;
13636                         rsurface.uselightmaptexture = false;
13637                         // simply scan ahead until we find a different texture or lightmap state
13638                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13639                                 ;
13640                 }
13641                 else
13642                 {
13643                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13644                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13645                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13646                         // simply scan ahead until we find a different texture or lightmap state
13647                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13648                                 ;
13649                 }
13650                 // render the range of surfaces
13651                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13652         }
13653         R_FrameData_ReturnToMark();
13654 }
13655
13656 float locboxvertex3f[6*4*3] =
13657 {
13658         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13659         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13660         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13661         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13662         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13663         1,0,0, 0,0,0, 0,1,0, 1,1,0
13664 };
13665
13666 unsigned short locboxelements[6*2*3] =
13667 {
13668          0, 1, 2, 0, 2, 3,
13669          4, 5, 6, 4, 6, 7,
13670          8, 9,10, 8,10,11,
13671         12,13,14, 12,14,15,
13672         16,17,18, 16,18,19,
13673         20,21,22, 20,22,23
13674 };
13675
13676 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13677 {
13678         int i, j;
13679         cl_locnode_t *loc = (cl_locnode_t *)ent;
13680         vec3_t mins, size;
13681         float vertex3f[6*4*3];
13682         CHECKGLERROR
13683         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13684         GL_DepthMask(false);
13685         GL_DepthRange(0, 1);
13686         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13687         GL_DepthTest(true);
13688         GL_CullFace(GL_NONE);
13689         R_EntityMatrix(&identitymatrix);
13690
13691 //      R_Mesh_ResetTextureState();
13692
13693         i = surfacelist[0];
13694         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13695                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13696                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13697                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13698
13699         if (VectorCompare(loc->mins, loc->maxs))
13700         {
13701                 VectorSet(size, 2, 2, 2);
13702                 VectorMA(loc->mins, -0.5f, size, mins);
13703         }
13704         else
13705         {
13706                 VectorCopy(loc->mins, mins);
13707                 VectorSubtract(loc->maxs, loc->mins, size);
13708         }
13709
13710         for (i = 0;i < 6*4*3;)
13711                 for (j = 0;j < 3;j++, i++)
13712                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13713
13714         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13715         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13716         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13717 }
13718
13719 void R_DrawLocs(void)
13720 {
13721         int index;
13722         cl_locnode_t *loc, *nearestloc;
13723         vec3_t center;
13724         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13725         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13726         {
13727                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13728                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13729         }
13730 }
13731
13732 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13733 {
13734         if (decalsystem->decals)
13735                 Mem_Free(decalsystem->decals);
13736         memset(decalsystem, 0, sizeof(*decalsystem));
13737 }
13738
13739 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)
13740 {
13741         tridecal_t *decal;
13742         tridecal_t *decals;
13743         int i;
13744
13745         // expand or initialize the system
13746         if (decalsystem->maxdecals <= decalsystem->numdecals)
13747         {
13748                 decalsystem_t old = *decalsystem;
13749                 qboolean useshortelements;
13750                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13751                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13752                 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)));
13753                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13754                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13755                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13756                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13757                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13758                 if (decalsystem->numdecals)
13759                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13760                 if (old.decals)
13761                         Mem_Free(old.decals);
13762                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13763                         decalsystem->element3i[i] = i;
13764                 if (useshortelements)
13765                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13766                                 decalsystem->element3s[i] = i;
13767         }
13768
13769         // grab a decal and search for another free slot for the next one
13770         decals = decalsystem->decals;
13771         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13772         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13773                 ;
13774         decalsystem->freedecal = i;
13775         if (decalsystem->numdecals <= i)
13776                 decalsystem->numdecals = i + 1;
13777
13778         // initialize the decal
13779         decal->lived = 0;
13780         decal->triangleindex = triangleindex;
13781         decal->surfaceindex = surfaceindex;
13782         decal->decalsequence = decalsequence;
13783         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13784         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13785         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13786         decal->color4ub[0][3] = 255;
13787         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13788         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13789         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13790         decal->color4ub[1][3] = 255;
13791         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13792         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13793         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13794         decal->color4ub[2][3] = 255;
13795         decal->vertex3f[0][0] = v0[0];
13796         decal->vertex3f[0][1] = v0[1];
13797         decal->vertex3f[0][2] = v0[2];
13798         decal->vertex3f[1][0] = v1[0];
13799         decal->vertex3f[1][1] = v1[1];
13800         decal->vertex3f[1][2] = v1[2];
13801         decal->vertex3f[2][0] = v2[0];
13802         decal->vertex3f[2][1] = v2[1];
13803         decal->vertex3f[2][2] = v2[2];
13804         decal->texcoord2f[0][0] = t0[0];
13805         decal->texcoord2f[0][1] = t0[1];
13806         decal->texcoord2f[1][0] = t1[0];
13807         decal->texcoord2f[1][1] = t1[1];
13808         decal->texcoord2f[2][0] = t2[0];
13809         decal->texcoord2f[2][1] = t2[1];
13810 }
13811
13812 extern cvar_t cl_decals_bias;
13813 extern cvar_t cl_decals_models;
13814 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13815 // baseparms, parms, temps
13816 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)
13817 {
13818         int cornerindex;
13819         int index;
13820         float v[9][3];
13821         const float *vertex3f;
13822         int numpoints;
13823         float points[2][9][3];
13824         float temp[3];
13825         float tc[9][2];
13826         float f;
13827         float c[9][4];
13828         const int *e;
13829
13830         e = rsurface.modelelement3i + 3*triangleindex;
13831
13832         vertex3f = rsurface.modelvertex3f;
13833
13834         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13835         {
13836                 index = 3*e[cornerindex];
13837                 VectorCopy(vertex3f + index, v[cornerindex]);
13838         }
13839         // cull backfaces
13840         //TriangleNormal(v[0], v[1], v[2], normal);
13841         //if (DotProduct(normal, localnormal) < 0.0f)
13842         //      continue;
13843         // clip by each of the box planes formed from the projection matrix
13844         // if anything survives, we emit the decal
13845         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]);
13846         if (numpoints < 3)
13847                 return;
13848         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]);
13849         if (numpoints < 3)
13850                 return;
13851         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]);
13852         if (numpoints < 3)
13853                 return;
13854         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]);
13855         if (numpoints < 3)
13856                 return;
13857         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]);
13858         if (numpoints < 3)
13859                 return;
13860         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]);
13861         if (numpoints < 3)
13862                 return;
13863         // some part of the triangle survived, so we have to accept it...
13864         if (dynamic)
13865         {
13866                 // dynamic always uses the original triangle
13867                 numpoints = 3;
13868                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13869                 {
13870                         index = 3*e[cornerindex];
13871                         VectorCopy(vertex3f + index, v[cornerindex]);
13872                 }
13873         }
13874         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13875         {
13876                 // convert vertex positions to texcoords
13877                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13878                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13879                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13880                 // calculate distance fade from the projection origin
13881                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13882                 f = bound(0.0f, f, 1.0f);
13883                 c[cornerindex][0] = r * f;
13884                 c[cornerindex][1] = g * f;
13885                 c[cornerindex][2] = b * f;
13886                 c[cornerindex][3] = 1.0f;
13887                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13888         }
13889         if (dynamic)
13890                 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);
13891         else
13892                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13893                         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);
13894 }
13895 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)
13896 {
13897         matrix4x4_t projection;
13898         decalsystem_t *decalsystem;
13899         qboolean dynamic;
13900         dp_model_t *model;
13901         const msurface_t *surface;
13902         const msurface_t *surfaces;
13903         const int *surfacelist;
13904         const texture_t *texture;
13905         int numtriangles;
13906         int numsurfacelist;
13907         int surfacelistindex;
13908         int surfaceindex;
13909         int triangleindex;
13910         float localorigin[3];
13911         float localnormal[3];
13912         float localmins[3];
13913         float localmaxs[3];
13914         float localsize;
13915         //float normal[3];
13916         float planes[6][4];
13917         float angles[3];
13918         bih_t *bih;
13919         int bih_triangles_count;
13920         int bih_triangles[256];
13921         int bih_surfaces[256];
13922
13923         decalsystem = &ent->decalsystem;
13924         model = ent->model;
13925         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13926         {
13927                 R_DecalSystem_Reset(&ent->decalsystem);
13928                 return;
13929         }
13930
13931         if (!model->brush.data_leafs && !cl_decals_models.integer)
13932         {
13933                 if (decalsystem->model)
13934                         R_DecalSystem_Reset(decalsystem);
13935                 return;
13936         }
13937
13938         if (decalsystem->model != model)
13939                 R_DecalSystem_Reset(decalsystem);
13940         decalsystem->model = model;
13941
13942         RSurf_ActiveModelEntity(ent, false, false, false);
13943
13944         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13945         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13946         VectorNormalize(localnormal);
13947         localsize = worldsize*rsurface.inversematrixscale;
13948         localmins[0] = localorigin[0] - localsize;
13949         localmins[1] = localorigin[1] - localsize;
13950         localmins[2] = localorigin[2] - localsize;
13951         localmaxs[0] = localorigin[0] + localsize;
13952         localmaxs[1] = localorigin[1] + localsize;
13953         localmaxs[2] = localorigin[2] + localsize;
13954
13955         //VectorCopy(localnormal, planes[4]);
13956         //VectorVectors(planes[4], planes[2], planes[0]);
13957         AnglesFromVectors(angles, localnormal, NULL, false);
13958         AngleVectors(angles, planes[0], planes[2], planes[4]);
13959         VectorNegate(planes[0], planes[1]);
13960         VectorNegate(planes[2], planes[3]);
13961         VectorNegate(planes[4], planes[5]);
13962         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13963         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13964         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13965         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13966         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13967         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13968
13969 #if 1
13970 // works
13971 {
13972         matrix4x4_t forwardprojection;
13973         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13974         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13975 }
13976 #else
13977 // broken
13978 {
13979         float projectionvector[4][3];
13980         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13981         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13982         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13983         projectionvector[0][0] = planes[0][0] * ilocalsize;
13984         projectionvector[0][1] = planes[1][0] * ilocalsize;
13985         projectionvector[0][2] = planes[2][0] * ilocalsize;
13986         projectionvector[1][0] = planes[0][1] * ilocalsize;
13987         projectionvector[1][1] = planes[1][1] * ilocalsize;
13988         projectionvector[1][2] = planes[2][1] * ilocalsize;
13989         projectionvector[2][0] = planes[0][2] * ilocalsize;
13990         projectionvector[2][1] = planes[1][2] * ilocalsize;
13991         projectionvector[2][2] = planes[2][2] * ilocalsize;
13992         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13993         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13994         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13995         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13996 }
13997 #endif
13998
13999         dynamic = model->surfmesh.isanimated;
14000         numsurfacelist = model->nummodelsurfaces;
14001         surfacelist = model->sortedmodelsurfaces;
14002         surfaces = model->data_surfaces;
14003
14004         bih = NULL;
14005         bih_triangles_count = -1;
14006         if(!dynamic)
14007         {
14008                 if(model->render_bih.numleafs)
14009                         bih = &model->render_bih;
14010                 else if(model->collision_bih.numleafs)
14011                         bih = &model->collision_bih;
14012         }
14013         if(bih)
14014                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
14015         if(bih_triangles_count == 0)
14016                 return;
14017         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
14018                 return;
14019         if(bih_triangles_count > 0)
14020         {
14021                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
14022                 {
14023                         surfaceindex = bih_surfaces[triangleindex];
14024                         surface = surfaces + surfaceindex;
14025                         texture = surface->texture;
14026                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
14027                                 continue;
14028                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
14029                                 continue;
14030                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
14031                 }
14032         }
14033         else
14034         {
14035                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
14036                 {
14037                         surfaceindex = surfacelist[surfacelistindex];
14038                         surface = surfaces + surfaceindex;
14039                         // check cull box first because it rejects more than any other check
14040                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
14041                                 continue;
14042                         // skip transparent surfaces
14043                         texture = surface->texture;
14044                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
14045                                 continue;
14046                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
14047                                 continue;
14048                         numtriangles = surface->num_triangles;
14049                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
14050                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
14051                 }
14052         }
14053 }
14054
14055 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
14056 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)
14057 {
14058         int renderentityindex;
14059         float worldmins[3];
14060         float worldmaxs[3];
14061         entity_render_t *ent;
14062
14063         if (!cl_decals_newsystem.integer)
14064                 return;
14065
14066         worldmins[0] = worldorigin[0] - worldsize;
14067         worldmins[1] = worldorigin[1] - worldsize;
14068         worldmins[2] = worldorigin[2] - worldsize;
14069         worldmaxs[0] = worldorigin[0] + worldsize;
14070         worldmaxs[1] = worldorigin[1] + worldsize;
14071         worldmaxs[2] = worldorigin[2] + worldsize;
14072
14073         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
14074
14075         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
14076         {
14077                 ent = r_refdef.scene.entities[renderentityindex];
14078                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
14079                         continue;
14080
14081                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
14082         }
14083 }
14084
14085 typedef struct r_decalsystem_splatqueue_s
14086 {
14087         vec3_t worldorigin;
14088         vec3_t worldnormal;
14089         float color[4];
14090         float tcrange[4];
14091         float worldsize;
14092         int decalsequence;
14093 }
14094 r_decalsystem_splatqueue_t;
14095
14096 int r_decalsystem_numqueued = 0;
14097 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
14098
14099 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)
14100 {
14101         r_decalsystem_splatqueue_t *queue;
14102
14103         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
14104                 return;
14105
14106         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
14107         VectorCopy(worldorigin, queue->worldorigin);
14108         VectorCopy(worldnormal, queue->worldnormal);
14109         Vector4Set(queue->color, r, g, b, a);
14110         Vector4Set(queue->tcrange, s1, t1, s2, t2);
14111         queue->worldsize = worldsize;
14112         queue->decalsequence = cl.decalsequence++;
14113 }
14114
14115 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
14116 {
14117         int i;
14118         r_decalsystem_splatqueue_t *queue;
14119
14120         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
14121                 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);
14122         r_decalsystem_numqueued = 0;
14123 }
14124
14125 extern cvar_t cl_decals_max;
14126 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
14127 {
14128         int i;
14129         decalsystem_t *decalsystem = &ent->decalsystem;
14130         int numdecals;
14131         int killsequence;
14132         tridecal_t *decal;
14133         float frametime;
14134         float lifetime;
14135
14136         if (!decalsystem->numdecals)
14137                 return;
14138
14139         if (r_showsurfaces.integer)
14140                 return;
14141
14142         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
14143         {
14144                 R_DecalSystem_Reset(decalsystem);
14145                 return;
14146         }
14147
14148         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
14149         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
14150
14151         if (decalsystem->lastupdatetime)
14152                 frametime = (cl.time - decalsystem->lastupdatetime);
14153         else
14154                 frametime = 0;
14155         decalsystem->lastupdatetime = cl.time;
14156         decal = decalsystem->decals;
14157         numdecals = decalsystem->numdecals;
14158
14159         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14160         {
14161                 if (decal->color4ub[0][3])
14162                 {
14163                         decal->lived += frametime;
14164                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
14165                         {
14166                                 memset(decal, 0, sizeof(*decal));
14167                                 if (decalsystem->freedecal > i)
14168                                         decalsystem->freedecal = i;
14169                         }
14170                 }
14171         }
14172         decal = decalsystem->decals;
14173         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
14174                 numdecals--;
14175
14176         // collapse the array by shuffling the tail decals into the gaps
14177         for (;;)
14178         {
14179                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
14180                         decalsystem->freedecal++;
14181                 if (decalsystem->freedecal == numdecals)
14182                         break;
14183                 decal[decalsystem->freedecal] = decal[--numdecals];
14184         }
14185
14186         decalsystem->numdecals = numdecals;
14187
14188         if (numdecals <= 0)
14189         {
14190                 // if there are no decals left, reset decalsystem
14191                 R_DecalSystem_Reset(decalsystem);
14192         }
14193 }
14194
14195 extern skinframe_t *decalskinframe;
14196 static void R_DrawModelDecals_Entity(entity_render_t *ent)
14197 {
14198         int i;
14199         decalsystem_t *decalsystem = &ent->decalsystem;
14200         int numdecals;
14201         tridecal_t *decal;
14202         float faderate;
14203         float alpha;
14204         float *v3f;
14205         float *c4f;
14206         float *t2f;
14207         const int *e;
14208         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
14209         int numtris = 0;
14210
14211         numdecals = decalsystem->numdecals;
14212         if (!numdecals)
14213                 return;
14214
14215         if (r_showsurfaces.integer)
14216                 return;
14217
14218         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
14219         {
14220                 R_DecalSystem_Reset(decalsystem);
14221                 return;
14222         }
14223
14224         // if the model is static it doesn't matter what value we give for
14225         // wantnormals and wanttangents, so this logic uses only rules applicable
14226         // to a model, knowing that they are meaningless otherwise
14227         if (ent == r_refdef.scene.worldentity)
14228                 RSurf_ActiveWorldEntity();
14229         else
14230                 RSurf_ActiveModelEntity(ent, false, false, false);
14231
14232         decalsystem->lastupdatetime = cl.time;
14233         decal = decalsystem->decals;
14234
14235         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
14236
14237         // update vertex positions for animated models
14238         v3f = decalsystem->vertex3f;
14239         c4f = decalsystem->color4f;
14240         t2f = decalsystem->texcoord2f;
14241         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14242         {
14243                 if (!decal->color4ub[0][3])
14244                         continue;
14245
14246                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
14247                         continue;
14248
14249                 // update color values for fading decals
14250                 if (decal->lived >= cl_decals_time.value)
14251                 {
14252                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
14253                         alpha *= (1.0f/255.0f);
14254                 }
14255                 else
14256                         alpha = 1.0f/255.0f;
14257
14258                 c4f[ 0] = decal->color4ub[0][0] * alpha;
14259                 c4f[ 1] = decal->color4ub[0][1] * alpha;
14260                 c4f[ 2] = decal->color4ub[0][2] * alpha;
14261                 c4f[ 3] = 1;
14262                 c4f[ 4] = decal->color4ub[1][0] * alpha;
14263                 c4f[ 5] = decal->color4ub[1][1] * alpha;
14264                 c4f[ 6] = decal->color4ub[1][2] * alpha;
14265                 c4f[ 7] = 1;
14266                 c4f[ 8] = decal->color4ub[2][0] * alpha;
14267                 c4f[ 9] = decal->color4ub[2][1] * alpha;
14268                 c4f[10] = decal->color4ub[2][2] * alpha;
14269                 c4f[11] = 1;
14270
14271                 t2f[0] = decal->texcoord2f[0][0];
14272                 t2f[1] = decal->texcoord2f[0][1];
14273                 t2f[2] = decal->texcoord2f[1][0];
14274                 t2f[3] = decal->texcoord2f[1][1];
14275                 t2f[4] = decal->texcoord2f[2][0];
14276                 t2f[5] = decal->texcoord2f[2][1];
14277
14278                 // update vertex positions for animated models
14279                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
14280                 {
14281                         e = rsurface.modelelement3i + 3*decal->triangleindex;
14282                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
14283                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
14284                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
14285                 }
14286                 else
14287                 {
14288                         VectorCopy(decal->vertex3f[0], v3f);
14289                         VectorCopy(decal->vertex3f[1], v3f + 3);
14290                         VectorCopy(decal->vertex3f[2], v3f + 6);
14291                 }
14292
14293                 if (r_refdef.fogenabled)
14294                 {
14295                         alpha = RSurf_FogVertex(v3f);
14296                         VectorScale(c4f, alpha, c4f);
14297                         alpha = RSurf_FogVertex(v3f + 3);
14298                         VectorScale(c4f + 4, alpha, c4f + 4);
14299                         alpha = RSurf_FogVertex(v3f + 6);
14300                         VectorScale(c4f + 8, alpha, c4f + 8);
14301                 }
14302
14303                 v3f += 9;
14304                 c4f += 12;
14305                 t2f += 6;
14306                 numtris++;
14307         }
14308
14309         if (numtris > 0)
14310         {
14311                 r_refdef.stats.drawndecals += numtris;
14312
14313                 // now render the decals all at once
14314                 // (this assumes they all use one particle font texture!)
14315                 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);
14316 //              R_Mesh_ResetTextureState();
14317                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14318                 GL_DepthMask(false);
14319                 GL_DepthRange(0, 1);
14320                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14321                 GL_DepthTest(true);
14322                 GL_CullFace(GL_NONE);
14323                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14324                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14325                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14326         }
14327 }
14328
14329 static void R_DrawModelDecals(void)
14330 {
14331         int i, numdecals;
14332
14333         // fade faster when there are too many decals
14334         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14335         for (i = 0;i < r_refdef.scene.numentities;i++)
14336                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14337
14338         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14339         for (i = 0;i < r_refdef.scene.numentities;i++)
14340                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14341                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14342
14343         R_DecalSystem_ApplySplatEntitiesQueue();
14344
14345         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14346         for (i = 0;i < r_refdef.scene.numentities;i++)
14347                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14348
14349         r_refdef.stats.totaldecals += numdecals;
14350
14351         if (r_showsurfaces.integer)
14352                 return;
14353
14354         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14355
14356         for (i = 0;i < r_refdef.scene.numentities;i++)
14357         {
14358                 if (!r_refdef.viewcache.entityvisible[i])
14359                         continue;
14360                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14361                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14362         }
14363 }
14364
14365 extern cvar_t mod_collision_bih;
14366 void R_DrawDebugModel(void)
14367 {
14368         entity_render_t *ent = rsurface.entity;
14369         int i, j, k, l, flagsmask;
14370         const msurface_t *surface;
14371         dp_model_t *model = ent->model;
14372         vec3_t v;
14373
14374         switch(vid.renderpath)
14375         {
14376         case RENDERPATH_GL11:
14377         case RENDERPATH_GL13:
14378         case RENDERPATH_GL20:
14379         case RENDERPATH_CGGL:
14380                 break;
14381         case RENDERPATH_D3D9:
14382                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14383                 return;
14384         case RENDERPATH_D3D10:
14385                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14386                 return;
14387         case RENDERPATH_D3D11:
14388                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14389                 return;
14390         case RENDERPATH_SOFT:
14391                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14392                 return;
14393         case RENDERPATH_GLES2:
14394                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14395                 return;
14396         }
14397
14398         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14399
14400 //      R_Mesh_ResetTextureState();
14401         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14402         GL_DepthRange(0, 1);
14403         GL_DepthTest(!r_showdisabledepthtest.integer);
14404         GL_DepthMask(false);
14405         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14406
14407         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14408         {
14409                 int triangleindex;
14410                 int bihleafindex;
14411                 qboolean cullbox = ent == r_refdef.scene.worldentity;
14412                 const q3mbrush_t *brush;
14413                 const bih_t *bih = &model->collision_bih;
14414                 const bih_leaf_t *bihleaf;
14415                 float vertex3f[3][3];
14416                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14417                 cullbox = false;
14418                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14419                 {
14420                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14421                                 continue;
14422                         switch (bihleaf->type)
14423                         {
14424                         case BIH_BRUSH:
14425                                 brush = model->brush.data_brushes + bihleaf->itemindex;
14426                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
14427                                 {
14428                                         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);
14429                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14430                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14431                                 }
14432                                 break;
14433                         case BIH_COLLISIONTRIANGLE:
14434                                 triangleindex = bihleaf->itemindex;
14435                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14436                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14437                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14438                                 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);
14439                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14440                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14441                                 break;
14442                         case BIH_RENDERTRIANGLE:
14443                                 triangleindex = bihleaf->itemindex;
14444                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14445                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14446                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14447                                 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);
14448                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14449                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14450                                 break;
14451                         }
14452                 }
14453         }
14454
14455         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14456
14457         if (r_showtris.integer || (r_shownormals.value != 0))
14458         {
14459                 if (r_showdisabledepthtest.integer)
14460                 {
14461                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14462                         GL_DepthMask(false);
14463                 }
14464                 else
14465                 {
14466                         GL_BlendFunc(GL_ONE, GL_ZERO);
14467                         GL_DepthMask(true);
14468                 }
14469                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14470                 {
14471                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14472                                 continue;
14473                         rsurface.texture = R_GetCurrentTexture(surface->texture);
14474                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14475                         {
14476                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14477                                 if (r_showtris.value > 0)
14478                                 {
14479                                         if (!rsurface.texture->currentlayers->depthmask)
14480                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14481                                         else if (ent == r_refdef.scene.worldentity)
14482                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14483                                         else
14484                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14485                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14486                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14487                                         RSurf_DrawBatch();
14488                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14489                                         CHECKGLERROR
14490                                 }
14491                                 if (r_shownormals.value < 0)
14492                                 {
14493                                         qglBegin(GL_LINES);
14494                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14495                                         {
14496                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14497                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14498                                                 qglVertex3f(v[0], v[1], v[2]);
14499                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14500                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14501                                                 qglVertex3f(v[0], v[1], v[2]);
14502                                         }
14503                                         qglEnd();
14504                                         CHECKGLERROR
14505                                 }
14506                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14507                                 {
14508                                         qglBegin(GL_LINES);
14509                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14510                                         {
14511                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14512                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14513                                                 qglVertex3f(v[0], v[1], v[2]);
14514                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14515                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14516                                                 qglVertex3f(v[0], v[1], v[2]);
14517                                         }
14518                                         qglEnd();
14519                                         CHECKGLERROR
14520                                         qglBegin(GL_LINES);
14521                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14522                                         {
14523                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14524                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14525                                                 qglVertex3f(v[0], v[1], v[2]);
14526                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14527                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14528                                                 qglVertex3f(v[0], v[1], v[2]);
14529                                         }
14530                                         qglEnd();
14531                                         CHECKGLERROR
14532                                         qglBegin(GL_LINES);
14533                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14534                                         {
14535                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14536                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14537                                                 qglVertex3f(v[0], v[1], v[2]);
14538                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14539                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14540                                                 qglVertex3f(v[0], v[1], v[2]);
14541                                         }
14542                                         qglEnd();
14543                                         CHECKGLERROR
14544                                 }
14545                         }
14546                 }
14547                 rsurface.texture = NULL;
14548         }
14549 }
14550
14551 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14552 int r_maxsurfacelist = 0;
14553 const msurface_t **r_surfacelist = NULL;
14554 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14555 {
14556         int i, j, endj, flagsmask;
14557         dp_model_t *model = r_refdef.scene.worldmodel;
14558         msurface_t *surfaces;
14559         unsigned char *update;
14560         int numsurfacelist = 0;
14561         if (model == NULL)
14562                 return;
14563
14564         if (r_maxsurfacelist < model->num_surfaces)
14565         {
14566                 r_maxsurfacelist = model->num_surfaces;
14567                 if (r_surfacelist)
14568                         Mem_Free((msurface_t**)r_surfacelist);
14569                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14570         }
14571
14572         RSurf_ActiveWorldEntity();
14573
14574         surfaces = model->data_surfaces;
14575         update = model->brushq1.lightmapupdateflags;
14576
14577         // update light styles on this submodel
14578         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14579         {
14580                 model_brush_lightstyleinfo_t *style;
14581                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14582                 {
14583                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14584                         {
14585                                 int *list = style->surfacelist;
14586                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14587                                 for (j = 0;j < style->numsurfaces;j++)
14588                                         update[list[j]] = true;
14589                         }
14590                 }
14591         }
14592
14593         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14594
14595         if (debug)
14596         {
14597                 R_DrawDebugModel();
14598                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14599                 return;
14600         }
14601
14602         rsurface.lightmaptexture = NULL;
14603         rsurface.deluxemaptexture = NULL;
14604         rsurface.uselightmaptexture = false;
14605         rsurface.texture = NULL;
14606         rsurface.rtlight = NULL;
14607         numsurfacelist = 0;
14608         // add visible surfaces to draw list
14609         for (i = 0;i < model->nummodelsurfaces;i++)
14610         {
14611                 j = model->sortedmodelsurfaces[i];
14612                 if (r_refdef.viewcache.world_surfacevisible[j])
14613                         r_surfacelist[numsurfacelist++] = surfaces + j;
14614         }
14615         // update lightmaps if needed
14616         if (model->brushq1.firstrender)
14617         {
14618                 model->brushq1.firstrender = false;
14619                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14620                         if (update[j])
14621                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14622         }
14623         else if (update)
14624         {
14625                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14626                         if (r_refdef.viewcache.world_surfacevisible[j])
14627                                 if (update[j])
14628                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14629         }
14630         // don't do anything if there were no surfaces
14631         if (!numsurfacelist)
14632         {
14633                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14634                 return;
14635         }
14636         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14637
14638         // add to stats if desired
14639         if (r_speeds.integer && !skysurfaces && !depthonly)
14640         {
14641                 r_refdef.stats.world_surfaces += numsurfacelist;
14642                 for (j = 0;j < numsurfacelist;j++)
14643                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14644         }
14645
14646         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14647 }
14648
14649 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14650 {
14651         int i, j, endj, flagsmask;
14652         dp_model_t *model = ent->model;
14653         msurface_t *surfaces;
14654         unsigned char *update;
14655         int numsurfacelist = 0;
14656         if (model == NULL)
14657                 return;
14658
14659         if (r_maxsurfacelist < model->num_surfaces)
14660         {
14661                 r_maxsurfacelist = model->num_surfaces;
14662                 if (r_surfacelist)
14663                         Mem_Free((msurface_t **)r_surfacelist);
14664                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14665         }
14666
14667         // if the model is static it doesn't matter what value we give for
14668         // wantnormals and wanttangents, so this logic uses only rules applicable
14669         // to a model, knowing that they are meaningless otherwise
14670         if (ent == r_refdef.scene.worldentity)
14671                 RSurf_ActiveWorldEntity();
14672         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14673                 RSurf_ActiveModelEntity(ent, false, false, false);
14674         else if (prepass)
14675                 RSurf_ActiveModelEntity(ent, true, true, true);
14676         else if (depthonly)
14677         {
14678                 switch (vid.renderpath)
14679                 {
14680                 case RENDERPATH_GL20:
14681                 case RENDERPATH_CGGL:
14682                 case RENDERPATH_D3D9:
14683                 case RENDERPATH_D3D10:
14684                 case RENDERPATH_D3D11:
14685                 case RENDERPATH_SOFT:
14686                 case RENDERPATH_GLES2:
14687                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14688                         break;
14689                 case RENDERPATH_GL13:
14690                 case RENDERPATH_GL11:
14691                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14692                         break;
14693                 }
14694         }
14695         else
14696         {
14697                 switch (vid.renderpath)
14698                 {
14699                 case RENDERPATH_GL20:
14700                 case RENDERPATH_CGGL:
14701                 case RENDERPATH_D3D9:
14702                 case RENDERPATH_D3D10:
14703                 case RENDERPATH_D3D11:
14704                 case RENDERPATH_SOFT:
14705                 case RENDERPATH_GLES2:
14706                         RSurf_ActiveModelEntity(ent, true, true, false);
14707                         break;
14708                 case RENDERPATH_GL13:
14709                 case RENDERPATH_GL11:
14710                         RSurf_ActiveModelEntity(ent, true, false, false);
14711                         break;
14712                 }
14713         }
14714
14715         surfaces = model->data_surfaces;
14716         update = model->brushq1.lightmapupdateflags;
14717
14718         // update light styles
14719         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14720         {
14721                 model_brush_lightstyleinfo_t *style;
14722                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14723                 {
14724                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14725                         {
14726                                 int *list = style->surfacelist;
14727                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14728                                 for (j = 0;j < style->numsurfaces;j++)
14729                                         update[list[j]] = true;
14730                         }
14731                 }
14732         }
14733
14734         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14735
14736         if (debug)
14737         {
14738                 R_DrawDebugModel();
14739                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14740                 return;
14741         }
14742
14743         rsurface.lightmaptexture = NULL;
14744         rsurface.deluxemaptexture = NULL;
14745         rsurface.uselightmaptexture = false;
14746         rsurface.texture = NULL;
14747         rsurface.rtlight = NULL;
14748         numsurfacelist = 0;
14749         // add visible surfaces to draw list
14750         for (i = 0;i < model->nummodelsurfaces;i++)
14751                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14752         // don't do anything if there were no surfaces
14753         if (!numsurfacelist)
14754         {
14755                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14756                 return;
14757         }
14758         // update lightmaps if needed
14759         if (update)
14760         {
14761                 int updated = 0;
14762                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14763                 {
14764                         if (update[j])
14765                         {
14766                                 updated++;
14767                                 R_BuildLightMap(ent, surfaces + j);
14768                         }
14769                 }
14770         }
14771         if (update)
14772                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14773                         if (update[j])
14774                                 R_BuildLightMap(ent, surfaces + j);
14775         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14776
14777         // add to stats if desired
14778         if (r_speeds.integer && !skysurfaces && !depthonly)
14779         {
14780                 r_refdef.stats.entities_surfaces += numsurfacelist;
14781                 for (j = 0;j < numsurfacelist;j++)
14782                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14783         }
14784
14785         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14786 }
14787
14788 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14789 {
14790         static texture_t texture;
14791         static msurface_t surface;
14792         const msurface_t *surfacelist = &surface;
14793
14794         // fake enough texture and surface state to render this geometry
14795
14796         texture.update_lastrenderframe = -1; // regenerate this texture
14797         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14798         texture.currentskinframe = skinframe;
14799         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14800         texture.offsetmapping = OFFSETMAPPING_OFF;
14801         texture.offsetscale = 1;
14802         texture.specularscalemod = 1;
14803         texture.specularpowermod = 1;
14804
14805         surface.texture = &texture;
14806         surface.num_triangles = numtriangles;
14807         surface.num_firsttriangle = firsttriangle;
14808         surface.num_vertices = numvertices;
14809         surface.num_firstvertex = firstvertex;
14810
14811         // now render it
14812         rsurface.texture = R_GetCurrentTexture(surface.texture);
14813         rsurface.lightmaptexture = NULL;
14814         rsurface.deluxemaptexture = NULL;
14815         rsurface.uselightmaptexture = false;
14816         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14817 }
14818
14819 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)
14820 {
14821         static msurface_t surface;
14822         const msurface_t *surfacelist = &surface;
14823
14824         // fake enough texture and surface state to render this geometry
14825         surface.texture = texture;
14826         surface.num_triangles = numtriangles;
14827         surface.num_firsttriangle = firsttriangle;
14828         surface.num_vertices = numvertices;
14829         surface.num_firstvertex = firstvertex;
14830
14831         // now render it
14832         rsurface.texture = R_GetCurrentTexture(surface.texture);
14833         rsurface.lightmaptexture = NULL;
14834         rsurface.deluxemaptexture = NULL;
14835         rsurface.uselightmaptexture = false;
14836         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14837 }